2017-02-13 32 views
1

У меня проблема с методом setInterval() в Javascript. Мой основной класс:Javascript setInterval не работает с этим. объекты

var sq1 = new Square(20, 20); 
window.onkeydown = function (e) 
{ 
    var key = e.keyCode ? e.keyCode : e.which; 
    if (key == 38) 
    { 
     sq1.moveUp(); 
    } 
} 

И у меня есть следующая функция конструктора.

function Square(x,y) 
{ 
    var multiplicator = 10; 

    this.xPos = x; 
    this.yPos = y; 

    this.domObj = document.createElement("div"); 
    this.domObj.style.position = "absolute"; 
    this.domObj.style.left = this.xPos * multiplicator + 'px'; 
    this.domObj.style.top = this.yPos * multiplicator + 'px'; 
    this.domObj.style.width = multiplicator + 'px'; 
    this.domObj.style.height = multiplicator + 'px'; 
    this.domObj.style.backgroundColor = "black"; 
    document.getElementById("idCanvas").appendChild(this.domObj); 

    this.moveUp = function() 
    { 
     this.yPos--; 
     this.domObj.style.top = (this.yPos * multiplicator) + 'px'; 
    } 
} 

Хорошо, что сейчас работает отлично, просто перемещая каждое событие keyUp 10px вверх. Но я хотел бы вызвать this.moveUp() каждые 1000 миллисекунд автоматически после события keyUp. Но когда я пытаюсь это:

this.moveUp = function() 
{ 
    setInterval(function() 
    { 
     this.yPos--; 
     this.domObj.style.top = (this.yPos * multiplicator) + 'px'; 
    }, 1000); 
} 

Я получаю сообщение об ошибке, что «это» является нулевым.

Как это исправить (желательно без jQuery)?

ответ

1

Вы должны связать setInterval к ​​одной и той же цели, как ваш класс.

this.moveUp = function() 
{ 
    setInterval(function() 
    { 
     this.yPos--; 
     this.domObj.style.top = (this.yPos * multiplicator) + 'px'; 
    }.bind(this), 1000); 
} 
+0

Проголосовать да? Думал, я сделал это правильно, но, возможно, нет? – Ribs

+0

не 'scope', а' target'. Кроме того, классы не задействованы. – Ben

+0

Да, я знаю, что классы не задействованы, но я для ясности использую те же термины, которые использовал OP. – Ribs

1

Целью является объект Window внутри setInterval

Вы либо должны захватить лексическую область и использовать его или использовать bind на жесткий затруднительное объектную ссылку на обработчик внутри setInterval области.

Использование лексического объема

this.moveUp = function() { 
    // capturing the lexical scope 
    var self = this; 
    setInterval(function() { 
    self.yPos--; 
    self.domObj.style.top = (self.yPos * multiplicator) + 'px'; 
    }, 1000); 
} 

Использование привязки

this.moveUp = function() { 
    setInterval(function() { 
    this.yPos--; 
    this.domObj.style.top = (this.yPos * multiplicator) + 'px'; 
    }.bind(this) , 1000); 
} 
+1

У вас есть золотой значок в JavaScript; вы знаете, что это дубликат многих вопросов? –

+0

Предполагая, что вам не нужна поддержка IE 8 и ниже, есть ли какая-нибудь причина * не * использовать '.bind()' в этом случае? –

+0

@MikeMcCaughan Большинство решений являются довольно универсальными в целом и требуют понимания всего содержимого, прежде чем понимать его. Мысль, дающая минималистский пример, помогла бы ОП, поскольку он новичок в JS. –