In the code below, the pushElement method works just fine when dealing with the "words" variable, but as soon as I run the popElement method, it fails on the "this.words.length" piece with the following error: "Uncaught TypeError: Cannot read property 'length' of undefined".
Any ideas?
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
EDIT: The code above is perfect. It was in my actual implementation of how I was using the code above. I'm using setInterval to call popElement() which changes the scope of "this". Read the full answer here:
http://forrst.com/posts/Javascript_Array_Member_Variable_is_Undefined_wi-g6V
@Chad already found the answer, but here is the explanation.
If you call the function like this:
AS.popElement();
the popElement function runs in the context of the AS object (meaning "this" refers to AS). But if you use setInterval (or any callback-style function) like this:
setInterval(AS.popElement, 1000);
you are only passing a reference to the popElement function. So when popElement is executed 1000 milliseconds later, it is executed in the global context (meaning "this" refers to window). You would get the same error if you called:
window.popElement();
A possible alternative to avoid this is to do the following:
setInterval(function() { return AS.popElement() }, 1000);
Another option could be to use the apply or call methods to set your context explicitly:
setInterval(AS.popElement.apply(AS), 1000);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With