tags:

views:

42

answers:

4

Can anyone explain why the Javascript from these slides fail?

var ninja = {
  yell: function(n){
    return n > 0 ? ninja.yell(n-1) + "a" : "hiy";
  }
};
assert( ninja.yell(4) == "hiyaaaa", "A single object isn't too bad, either." );

var samurai = { yell: ninja.yell };
var ninja = null;

try {
  samurai.yell(4);
} catch(e){
  assert( false, "Uh, this isn't good! Where'd ninja.yell go?" );
}
+2  A: 

You wrote ninja = null before calling the function.
Javascript functions capture outer variables by reference, so the ninja identifier inside the function refers to the current value of the variable.

SLaks
Why was this downvoted?
SLaks
+3  A: 

This reference is still maintained:

var samurai = { yell: ninja.yell };

So that call to .yell() is fine, however this one isn't:

return n > 0 ? ninja.yell(n-1) + "a" : "hiy";

That call's actually referencing ninja which is now null, and null.yell() isn't a function :)

Here's a modified version that shows the problem.

Nick Craver
+1  A: 

Samurai.yell is a "copy" of the function from ninja. In that function, it referenced ninja, which no longer existed when Samurai.yell was executed.

CD Sanchez
+4  A: 

The recursive function call uses the ninja reference inside yell(), and when you set that to null it can't call ninja.yell anymore because ninja is null.

Change:

return n > 0 ? ninja.yell(n-1) + "a" : "hiy";

To:

return n > 0 ? this.yell(n-1) + "a" : "hiy";

And it works.

chubbard