Переменная члена массива Javascript не определена методом Prototype - PullRequest
5 голосов
/ 26 февраля 2011

В приведенном ниже коде метод pushElement прекрасно работает при работе с переменной «words», но как только я запускаю метод popElement, он завершается с ошибкой на фрагменте «this.words.length» со следующей ошибкой: Msgstr "Uncaught TypeError: Невозможно прочитать свойство 'length' из неопределенного".

Есть идеи?

function AnimationStack() {
    this.words = [];
}

AnimationStack.prototype.pushElement = function(element) {
    this.words.push(element);
}

AnimationStack.prototype.popElement = function() {
    if (this.words.length>0) {
        var element = this.words.shift();
        return element;
    } else {
        return null;
    }
}

var AS = new AnimationStack();

var element = $("<div></div>");
AS.pushElement(element); // works perfect
AS.pushElement(element); // works perfect
AS.pushElement(element); // works perfect

var pop = AS.popElement(); // always fails

РЕДАКТИРОВАТЬ: Код выше идеально. Это было в моей реальной реализации того, как я использовал код выше. Я использую setInterval для вызова popElement (), который меняет область действия «this». Читайте полный ответ здесь:

http://forrst.com/posts/Javascript_Array_Member_Variable_is_Undefined_wi-g6V

1 Ответ

1 голос
/ 11 марта 2011

@ Чад уже нашел ответ, но вот объяснение.

Если вы вызываете функцию следующим образом:

AS.popElement();

, функция popElement запускается в контексте объекта AS(что означает «это» относится к AS).Но если вы используете setInterval (или любую функцию в стиле обратного вызова) следующим образом:

setInterval(AS.popElement, 1000);

, вы только передаете ссылку на функцию popElement.Поэтому, когда popElement выполняется через 1000 миллисекунд, он выполняется в глобальном контексте (что означает «это» относится к окну).Вы бы получили ту же ошибку, если бы позвонили:

window.popElement();

Возможная альтернатива, позволяющая избежать этого, заключается в следующем:

setInterval(function() { return AS.popElement() }, 1000);

Другим вариантом может быть использование apply или callметоды для явного задания контекста:

setInterval(AS.popElement.apply(AS), 1000);
...