2015-01-31 3 views
0

Я новичок в JavaScript, и я пытаюсь написать простой игровой цикл. Вот моя цель игры:'this' в методе объекта

var Game = { 
    timers: [], 
    start: timestamp(), 
    stopTimers: function() { 
     consoleEntry('All timers have been stopped.'); 
     this.timers.length = 0; 
    }, 
    update: function(elasped) { 
     for (var i = 0; i < this.timers.length; ++i) { 
      var timer = elapsed - timers[i].startTime; 
      console.log('Timer: ' + timer + '. Timer interval: ' + this.timers[i].interval + '.'); 
      if (this.timers[i].interval <= timer) { 
       this.timers[i].times--; 
       this.timers[i].report = true; 
       if (this.timers[i].times != 0) { 
        this.timers[i].startTime = elapsed; 
       } 
      } 
     } 
    }, 
    render: function() { 
     for (var i = 0; i < this.timers.length; ++i) { 
      if (this.timers[i].report) { 
       consoleEntry('Timer: ' + this.timers[i].name + ' (' + this.timers[i].times + ' remaining).'); 
       this.timers[i].report = false; 
       if (this.timers[i].times == 0) this.timers.splice(i, 1); 
      } 
     } 
    }, 
    gameLoop: function() { 
     var elapsed = timestamp() - this.start; 
     this.update(elapsed); 
     this.render(); 
     requestAnimationFrame(this.gameLoop); 
    }, 
    startGame: function() { 
     console.log(this); 
     requestAnimationFrame(this.gameLoop); 
    } 
} 

Я называю Game.startGame();, когда <body> нагрузки. Вот ошибка, которую я получаю: Uncaught TypeError: undefined is not a function. Он относится к this.update(elapsed); внутри функции gameLoop. По какой-то причине я не понимаю, когда я делаю console.log(this) внутри startGame Я получаю объект, к которому он принадлежит (что является удивительным), но когда я делаю то же самое внутри gameLoop, я получаю объект Window.

Кто-нибудь знает, почему это происходит?

Спасибо!

+0

Вы называете новую игру, а затем вызываете startGame на новый объект, который вы только что создали? Или вы буквально просто называете Game.startGame()? – Jazzepi

+1

буквально :) Я не должен, а? – user1563544

+1

Вы должны привязать 'this' к функции, которую вы передаете' requestAnimationFrame() '-' requestAnimationFrame (this.gameLoop.bind (this)); ' – Pointy

ответ

0

Самый простой способ увидеть, что означает это «это», - это посмотреть, какой объект стоит перед функцией в точечной ноте вызывающего оператора.

Например, если вы говорите,

document.createElement(..) 

В определении функции, в «это» будет относиться к документу.

Все функции имеют такой объект. Глобальные функции относятся к окну.

window.console === console; // true 

Итак, когда вы выполняете «requestAnimationFrame», «это» относится к окну.

Вы можете указать, к чему относится это «это», используя функции прототипа функции «звонок» и «применить».

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

Я не особо знаком с window.requestAnimationFrame, но и для ваших целей я мог бы предложить один из двух вариантов:

Может быть, просто с помощью «вызов» может работать

requestAnimationFrame.call(this, this.gameLoop); 

Или, если нет, замыкание сделает трюк.

requestAnimationFrame(
    (function(g){ 
     return function() { g.gameLoop(); }; 
    })(this) 
); 

И, для получения дополнительной информации о "это" в JavaScript:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

Надеется, что это помогает!

+0

Любая функция, глобальная или иная, которая вызывается без явного приемника, получает 'window' как значение' this' в нестрогом режиме; в строгом режиме он получает 'undefined'. – Pointy

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