2013-05-04 4 views
0

Я пытаюсь понять методы JavaScript «ООП», и сегодня я начал писать небольшое тестовое приложение. В принципе, это игровой цикл, и каждый координат обновления должен быть увеличен, чтобы перемещаться элемент HTML.Модуль/прототип и несколько экземпляров

Проблема заключается в том, что я хочу иметь возможность запускать более одного экземпляра приложения, и поэтому я пытаюсь сохранить данные экземпляра в this, но то, что сохраняется в моем конструкторе, и метод exec() недоступен в частный метод update(). Что, кажется, офицер, проблема?

var Jsloth = (function() { 
    var Jsloth = function() { 
     var sloth = document.createElement('div'); 
     var attr = document.createAttribute('class'); 
     attr.value = 'sloth'; 
     sloth.setAttributeNode(attr); 
     this.sloth = document.getElementsByTagName('body')[0].appendChild(sloth); 
    }; 

    var exec = function() { 
     this.x = 0; 
     this.y = 0; 
     var that = this; 
     setInterval(function() { 
      that.update(); 
     }, 1000/10); 
    }; 

    var update = function() { 
     this.x++; 
     this.y++; 
     this.sloth.style.left = this.x + 'px'; 
     this.sloth.style.bottom = this.y + 'px'; 
    }; 

    Jsloth.prototype.constructor = Jsloth; 
    Jsloth.prototype.exec = exec; 
    Jsloth.prototype.update = update; 

    return Jsloth; 
})(); 

var sloth1 = new Jsloth(); 
sloth1.exec(); 

Edit: Обновленный код с рабочим решением!

+1

Если вы объявляете функции с операторами объявления функций, вы можете указать им имена, которые будут отображаться в трассировке стека при отладке. Нет никаких причин объявлять их анонимными функциональными выражениями, например, для «exec», «update» и внутреннего «Jsloth». – Pointy

+0

'function exec() {/ * ... * /}' - Я согласен, что это запутывает; эта тенденция объявления функций, как вы начали появляться в сообщениях в блоге и т. д. пару лет назад. На самом деле это работает очень хорошо, но это ... ну, это сводит меня с ума, лично :-) – Pointy

+0

Ха-ха. Я приобрел книгу Крокфорда, надеюсь, что она меня прямо расставит. Когда вы выполняете 'function exec() {/ * ... * /}', могу ли я использовать мое пространство имен 'Jsloth' и' prototype'? Bah, в Java есть только один способ ... При поиске JS существует 8 способов (наклонить его). – Viktor

ответ

2

Вы не добавили update к прототипу. Значение this в этом методе, скорее всего, будет window.

Изменить вызов от этого:

update(); 

Для этого:

update.call(this); 

Или добавьте update к .prototype:

Jsloth.prototype.update = update; 

и использования:

this.update(); 

Но если вы собираетесь позвонить update() из setInterval(), вам необходимо обеспечить надлежащее this значение.

Для этого вы можете передать анонимную функцию и сохранить ссылку на внешнее значение this в переменной.

var exec = function() { 
    this.x = 0; 
    this.y = 0; 
    var that = this; 
    setInterval(function() { 
     that.update(); 
     //update.call(that); // if you didn't add update() to the .prototype 
    }, 1000/10); 
}; 
+0

Отлично! Мои Java-инстинкты сказали мне не добавлять 'update()' в 'prototype', так как это не для публичного доступа, но, возможно, в этом нет вреда. Он работает сейчас, но по какой-то причине я не могу создать два экземпляра. Второй не появится в DOM ... Знаете ли вы, почему? – Viktor

+0

@squint NB: не забывайте, что можно создавать методы для каждого экземпляра (как свойства), не находясь на прототипе, и они все равно потребуют 'obj.method()' вызывающий синтаксис. – Alnitak

+0

@Viktor: Не знаете, почему. Пока каждый новый элемент создается каждый раз при вызове конструктора, он должен работать. Если вы попытаетесь повторно добавить один и тот же элемент, он просто будет перемещен. Вы не положили элемент на прототип, не так ли? – 2013-05-04 23:31:49

3

В JavaScript this есть (почти) полностью решает как вы вызываете функцию, а не где/как это определено.

Путь вы звоните update:

update(); 

... this будет глобальный объект (window в браузерах), или undefined, если вы используете "use strict".

Чтобы установить this в update используйте call или apply:

update.call(this); 
// or 
update.apply(this); 

Больше (в моем блоге):

+0

Спасибо за ваше объяснение! Я даю ответ косоглазие, хотя, так как он видел мою проблему setInterval(). Тем не менее, я голосую за тебя! – Viktor

+0

Ваш блог кажется заслуживающим внимания, хотя, закладок! – Viktor

+0

@Viktor: Действительно, он сделал, +1 к нему. Наслаждайтесь блогами! :-) –

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