Tiago Castro Tiago Castro - 1 month ago 8
Javascript Question

Can't have access to a variable using call in Javascript

Im studying javascript and learning how to use "call".I create this code and I dont know why I cant have access to this variable "Time".

var MyObject;
(function(MyObject) {
var Runner = (function() {
function Runner(time) {
this.time = time;
}
var myFunctionArray = [];
Runner.prototype.execute = function() {
myFunctionArray[0]();
}

Runner.prototype.newTest = function(index, execute) {
var test = function() {
return execute.call(this);
}
myFunctionArray.push(test);
}
return Runner;
})();
MyObject.Runner = Runner;
})(MyObject|| (MyObject= {});

var myNewObj = new MyObject.Runner(1000);
myNewObj.newTest('1',function() {
console.log(this.time) //output: undefined
});


So how can I get time value inside newTest function?

Answer

Issue is in newTest function

Runner.prototype.newTest = function(index, execute) {
  var test = function() {
    return execute.call(this);
  }
  myFunctionArray.push(test);
}

Here this is pointing to test and not Runner. You will have to save context in a variable and then set it in call.

Runner.prototype.newTest = function(index, execute) {
  var self = this;
  var test = function() {
    return execute.call(self);
  }
  myFunctionArray.push(test);
}

.call + self

var MyObject;
(function(MyObject) {
  var Runner = (function() {
    function Runner(time) {
      this.time = time;
    }
    var myFunctionArray = [];
    Runner.prototype.execute = function() {
      myFunctionArray[0]();
    }

    Runner.prototype.newTest = function(index, execute) {
      var self = this;
      var test = function() {
        return execute.call(self);
      }
      myFunctionArray.push(test);
    }
    return Runner;
  })();
  MyObject.Runner = Runner;
})(MyObject || (MyObject = {}));

var myNewObj = new MyObject.Runner(1000);
myNewObj.newTest('1', function() {
  console.log(this, this.time) //output: undefined
});
myNewObj.execute()

.bind

As commented, you can even use .bind

var MyObject;
(function(MyObject) {
  var Runner = (function() {
    function Runner(time) {
      this.time = time;
    }
    var myFunctionArray = [];
    Runner.prototype.execute = function() {
      myFunctionArray[0]();
    }

    Runner.prototype.newTest = function(index, execute) {
      myFunctionArray.push(execute.bind(this));
    }
    return Runner;
  })();
  MyObject.Runner = Runner;
})(MyObject || (MyObject = {}));

var myNewObj = new MyObject.Runner(1000);
myNewObj.newTest('1', function() {
  console.log(this, this.time) //output: undefined
});
myNewObj.execute()

Comments