tags:

views:

17

answers:

1

I am having troubles using shift() to call functions I have put in an array. I have put together a simple example illustrating the problem.

Essentially the function gets called, however, the changes to variables in the function do not stick.

<html>
<head>
<script type="text/javascript">
Taco = function() {};
Taco.prototype.init = function() {
  this.ex1 = "ex1 in init()";
  alert(this.ex1);
};
</script>
</head>
<body>
<input type="Submit" onClick="withShift();" value="withShift"/>
<div id="div1">
</div>
<input type="Submit" onClick="noShift();" value="noShift"/>
<div id="div2">
</div>
<script type="text/javascript">
// This calls init but does not hold the value of ex1 after the call
withShift = function() {
taco = new Taco();
  funcQ = [];
  funcQ.push(taco.init);
  funcQ.shift()(); 

  div1 = document.getElementById("div1")
  div1.appendChild(document.createTextNode(taco.ex1));
};

// this calls init and it holds the value...
noShift = function() {
  taco2 = new Taco();
  taco2.init();
  div1 = document.getElementById("div2")
  div1.appendChild(document.createTextNode(taco2.ex1));
}
</script>
</body>
</html>

Thank you in advance for any suggestions.

+1  A: 

JavaScript does not remember the this argument when you pass method pointers. You have to use the call or apply method on the function object to explicitly pass this.

Using taco.init is roughly the same as using Taco.prototype.init when it comes to passing function pointers. Here's what would be the working way:

taco = new Taco();
funcQ = [];
funcQ.push(taco.init);
// pass taco first, and the non-hidden function arguments after;
// in this case, no other argument
funcQ.shift().call(taco);

If you can't use this kind of syntax, you may use anonymous functions:

taco = new Taco();
funcQ = [];
funcQ.push(function() { taco.init(); });
funcQ.shift()();

In opposition to the object.method syntax that doesn't carry the this argument, closures are reliable.

zneak