0

Thanks in advance for any responses: I don't think this is a duplicate: I reviewed that article in the first comment, that is just a general breakdown of objects and using "this" within javascript.

My other this.function's perform just fine, so I at least have the basics of JS Obj's figured out.

This issue is related to using .map() with a this.function within a constructed object.

The following Google Appscript code uses .map() to update a string in a 2d array. [[string, int],[string, int]]

For some reason, when using .map() it is am unable to access the function "this.removeLeadingZero". If that same function is placed outside of the OBJ it can be called and everything works just fine. For some reason the system claims row[0] is an [object, Object] but when I typeof(row[0]) it returns "string" as it should.

Error: TypeError: Cannot find function removeLeadingZero in object [object Object]. (line 106, file "DEEP UPC MATCH")

Is there any issue using this.function's with .map() inside an object or am I using an incorrect syntax?

function test2DMapping(){
  var tool = new WorkingMappingExample()
  var boot = tool.arrayBuild();
  Logger.log(boot)
}

function WorkingMappingExample(){
    this.arr= [["01234", 100],["401234", 101],["012340", 13],["01234", 0422141],["01234", 2],["12340",3],["01234", 1],["01234", 2],["12340",3],["01234", 1],["01234", 2],["12340",3],["01234", 1],["01234", 2],["12340",3]];
    //mapping appears faster that normal iterations

    this.arrayBuild = function(){
      var newArray1 = 
        this.arr.map( function( row ) {

        **var mUPC = removeLeadingZero2(row[0])**   //working
        **var mUPC = this.removeLeadingZero(row[0])**  // not working 
        var index = row[1]

        Logger.log(mUPC + " " + index)
          row = [mUPC, index]
          return row
        } )
     return newArray1;
     };
  }; //end of OBJ


//THE NEXT 2 FUNCTIONS ARE WORKING OUTSIDE OF THE OBJECT
function removeLeadingZero2(upc){
    try {
        if (typeof(upc[0]) == "string"){
              return upc.replace(/^0+/, '')
        } else {
          var stringer = upc.toString();
          return stringer.replace(/^0+/, '')
        }
    } catch (err) {
      Logger.log(err);
      return upc;
    }
  }

 function trimFirstTwoLastOne (upc) {
    try {
        return upc.substring(2, upc.length - 1); //takes off the first 2 #'s off and the last 1 #'s     
    } catch (err) {
      Logger.log(err);
      return upc;
    }  
  }
Leonardo Alves Machado
  • 2,481
  • 7
  • 31
  • 43
r.zip
  • 24
  • 4
  • 1
    Possible duplicate of [How does the "this" keyword work?](https://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work) – PeterMader Sep 22 '17 at 18:51

2 Answers2

2

Inside the function that you pass to map, this doesn't refer to what you think it does. The mapping function has its own this, which refers to window, normally:

var newArray1 = this.arr.map(function(row) {
  // this === window
  var mUPC = this.removeLeadingZero(row[0]);
  var index = row[1];
  Logger.log(mUPC + " " + index);
  return [mUPC, index];
});

You have four options:

  1. Array#map takes a thisArg which you can use to tell map what the this object in the function should be:
var newArray1 = this.arr.map(function(row) {
  // this === (outer this)
  var mUPC = this.removeLeadingZero(row[0]);
  // ...
}, this); // pass a thisArg
  1. Manually bind the function:
var newArray1 = this.arr.map(function(row) {
  // this === (outer this)
  var mUPC = this.removeLeadingZero(row[0]);
  // ...
}.bind(this)); // bind the function to this
  1. Store a reference to the outer this:
var self = this;
var newArray1 = this.arr.map(function(row) {
  // self === (outer this)
  var mUPC = self.removeLeadingZero(row[0]);
  // ...
});
  1. Use an arrow function:
var newArray1 = this.arr.map(row => {
  // this === (outer this)
  var mUPC = this.removeLeadingZero(row[0]);
  // ...
});

Additionally, you could stop using this and new.

PeterMader
  • 5,739
  • 1
  • 16
  • 27
  • great set of answers. I figured out your #3 on my own, but 1 and 2 look solid as well. Unfortunately, #4 doesn't work because Google Appscript isn't the latest JS standard so no => ... Either way thanks again! – r.zip Sep 22 '17 at 19:27
0

I have solved this issue and below is the answer in case anyone else runs into this:

this needs to be placed into a variable:
var _this = this;

and then you can call it within the object: var mUPC = _this.removeLeadingZero(row[0])

Javascript scope strikes again!

r.zip
  • 24
  • 4