开发者

What technique is used here in this JavaScript code?

var a = (function(y,x) {
    var x = null;
    return {
        foo: function(x){ return this.bar(x * y); },
        bar: function(x){ return x + y; }
    }
})(3,4);

Would someone please be kind enough to explain me what exactly is 开发者_如何学Chappening in the above code? Where can I read or refer on advanced JavaScript techniques? Sorry, I'm just starting to learn JavaScript.


This is a closure.

An anonymous function is created then immediately executed and its return value assigned to a.

The variables passed to it are rendered (more or less) inaccessible to interference from other functions.

For some reason, the x=4 is immediately overwritten with x=null in the outer function. Then overwritten again in the arguments for each inner function. This renders it pointless to pass it in in the first place.


What is happening is that you've created an anonymous function that takes 2 parameters x and y. The anonymous function executes immediately.

It creates a local variable x and assigns it null. This means absolutely nothing in this example. and is there to demonstrate that the parameter x overrides the locally instantiated x and can only be accessed with the this keyword.

The anonymous function then returns an object with properties foo and bar that are both functions that both take a parameter x.

What's most interesting is that the parameter y from the anonymous function becomes "locked" inside the foo and bar functions, so that when you call:

 a.foo(4);   // output 15
 a.foo(2);   // output 9

In the above example, the 4 is passed into the function foo as the x parameter. The product of 4 and 3, the original y value passed in the anonymous function, is 12. This product is passed into the bar function, where 12 is added to that same locked-in y value of 3, which gives you the sum of 15.

The same process happens for foo(2).

My suggestion is to pull up Firefox with Firebug and paste that code into the console and run it. Then call a.foo and a.bar with different values and trace the execution. This will help you better understand what is going on in the code.

Breakdown of function execution with substitution:

 a.foo(4);
 function(4) { return this.bar(4 * 3); }
 function(4) { return function(4 * 3) { return (4 * 3) + 3; } };

 function(4) { return function(12) { return (12) + 3; } };
 function(4) { return function(12) { return 15; } );

 function(4) { return 15; }
 15

I would also recommend that you check out this example of closures, but without the anonymous function. Removing the anonymous component may help make this more clear.

In fact, here is your example from above, but without anonymous functions:

function fooBar(y,x) {
    var x = null;
    return {
        foo: function(x){ return this.bar(x * y); },
        bar: function(x){ return x + y; }
    }
}

var b = fooBar(3,4);


b.foo(2);   // output 9
b.foo(4);   // output 15

So in the above example, fooBar(3,4) returns an object that contains two functions foo and bar, with the 3 locked in as the y parameter.

JavaScript Kit - Closures 101. They're Not Magic, is another great resource that will help explain the purpose of closures, as well as what it means behind the scenes.


See http://jibbering.com/faq/notes/closures/ -- it explains the details in a readable way.

This sort of "double binding" is required because only new function scopes introduce new execution contexts (see the above link for what that means :-) This is just how ECMAScript works -- in languages like C, Java or C#, each new block [generally speaking] introduces a new lexical variable scope.

Edit (closer inspection):

var a = (function(y,x) {
    // This is a new function body, so it introduces a new lexical scope
    // The following line is questionable. Function parameters always belong to
    // the function scope. It has the same effect a `x = null` (no var) here
    // but since it just discards the value, is still questionable...
    var x = null;
    return {
        // Both of these functions have their own function scope and
        // since they are created here they can "bind" to free variables
        // in the enclosing scope through the [[scope]] chain (implicitly).
        // Inside the x refers to the parameter passed in, respectively
        // and does NOT refer to the x above.
        foo: function(x){ return this.bar(x * y); },
        bar: function(x){ return x + y; }
    }
})(3,4);
// Then the function is executed which results in the object that contains
// foo and bar properties which contain functions that "close over" y.

And a cleaned-up version with the same semantics, to show which variables bindings are really happen

var a = (function(y,__ignored) {
    return {
        foo: function(x){ return this.bar(x * y); },
        bar: function(x){ return x + y; }
    }
})(3,4);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜