简体   繁体   中英

Why isn't this recognized as a function?

I have this function in my object:

var time = {

    warps : 3,
    warpCounter : 50,

    warp : function(){
        if (this.warps > 0){
            this.warps--;
            this.warpLoop = 50;
            this.warpLoop(); 
        }
    },

    warpLoop : function(){
       setTimeout(function () {
          this.increment();              
          if (warpCounter--){
            this.warpLoop();
          }else{
            if(this.warps > 0){
              htmlInteraction.enableButton('warp-button');
            }
          }
       }, 100);
    },

};

When I try and call it from another method (using this.warpLoop() ) I get:

Uncaught TypeError: Property 'warpLoop' of object #<Object> is not a function 

Why is this?

this context in setTimeout changes, you can use closures to keep the this context.

var test={
warpLoop : function(){
   var me=this;//set closure to get the right this context
   setTimeout(function () {
     console.log("this is:",this); // is window
     console.log("me is:",me); // is test
     // can call me.warpLoop() but not this.warpLoop()
   }, 100);
}
}
test.warpLoop();

your code can look like this:

var time = {

    warps : 3,
    warpCounter : 3,

    warp : function(){
        if (this.warps > 0){
            this.warps--;
            this.warpLoop = 50;
            this.warpLoop(); 
        }
    },

    warpLoop : function(){
       //the setTimeout calls me.warpCounter not this.warpCounter
       // wich is the same as window.warpCounter since the next
       // line is not part of the setTimeout execution you can
       // use this
       console.log("warpLoop called,warpCounter is",this.warpCounter);
       var me=this;
       setTimeout(function () {
          //me.increment();              
          if (me.warpCounter--){
            me.warpLoop();
          }else{
            if(me.warps > 0){
              //htmlInteraction.enableButton('warp-button');
            }
          }
       }, 100);
    },

};
time.warpLoop();

The this value in JavaScript is not lexically defined. It's defined by the manner in which the function was invoked.

A typical fix is to store the value of this in a variable in the enclosing scope, then reference it in the inner scope.

var that = this;

setTimeout(function() {
    that.whatever()
}, 1000)

While you could also bind the outer this value to your callback using Function.prototype.bind() , you seem to have an .increment() method that isn't throwing the error. So binding may break that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM