2013-05-21 2 views
0

У меня есть эта функция в моем объекте:Почему это не признается функцией?

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); 
    }, 

}; 

Когда я пытаюсь вызвать его из другого метода (с помощью this.warpLoop()) я получаю:

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

Почему это?

+0

@dystroy Я добавил весь объект. – fredley

+1

Вам нужно прочитать, как это работает в Javascript. Это может быть довольно запутанным, пока вы не поймете это (и еще более сбиваете с толку, если думаете, что понимаете это!). В Интернете есть много и много * ресурсов; это очень распространенная проблема. [Это будет хорошей отправной точкой] (http://stackoverflow.com/questions/3127429/javascript-this-keyword), но есть еще много, если вы его ищете. – Spudley

ответ

3

Оценка: this Значение в JavaScript не определено lexically. Он определяется тем, как функция была вызвана.

Типичное исправление заключается в том, чтобы сохранить значение this в переменной в охватывающей области, а затем ссылаться на нее во внутренней области.

var that = this; 

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

В то время как вы можете также связать внешний this значение обратного вызова с помощью Function.prototype.bind(), вы, кажется, есть .increment() метод, который не бросает ошибку. Поэтому привязка может нарушить это.

+0

Я попытался изменить 'warpLoop', чтобы принять аргумент' self' и передал его, хотя - стиль python, но это не помогло ... – fredley

+0

@TomMedley: Нет, это не помогло бы, если вы не определили 'self' переменная для ссылки на объект. В принципе, если вы хотите, чтобы значение 'this' в' warpLoop' ссылалось на конкретный объект, вы должны вызывать 'warpLoop' из этого объекта, как в' my_object.warpLoop() '. Вот почему мы сохраняем внешнее значение this this в переменной. –

+0

Вы можете использовать затворы, как в примере. Обратитесь в MDN за информацией о закрытии. – HMR

5

Этот контекст в setTimeout изменяется, вы можете использовать закрытие, чтобы сохранить этот контекст.

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(); 

ваш код может выглядеть следующим образом:

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(); 
+0

Я пробовал это, но я все еще получаю ошибку, что это не функция ... – fredley

+0

Что-то странное происходит, я могу вызвать 'warpLoop' извне объекта, но не из другого метода внутри (я получаю ошибку в мой вопрос). Почему это? – fredley

+0

@TomMedley Я включил код, специфичный для вашей ситуации. прокомментировал функции, которые вы не опубликовали, поскольку это приведет к возникновению ошибки. – HMR

Смежные вопросы