Is a separate closure instance created for each nested function?
Apologies if my terminology is a little off... When a one function wraps another and a closure is c开发者_如何学Goreated, is a new instance of the closure ("space in memory"?) created each time the outer function is called?
From my code here I believe the answer to be yes:
(function(){
var ob = {}, names=['one', 'two'], i=0;
var outer = function(val){
ob[names[i++]] = function(){
return val;
};
};
outer(3);
outer(999);
console.log(ob.one());
console.log(ob.two());
})();
Given that the result is
3
999
rather than
999
999
it appears as if ob.one
points to a different closure instance to ob.two
-each with its own value for val
.
Is it more than my terminology that's confused?
Is a seperate closure instance created for each nested function?
yes, this is a desirable feature
An even more desirable feature would be block-level scoping, which javascript does not have. In fact, it is necessary to abuse nested functions in order to do nested for
-loops in javascript, or else the variable binding will be mutated behind your back (e.g. if you hand it off to a callback, which you yourself demonstrate; just imagine the functions you're defining are, for example, onClick handlers for different elements; you will want the binding to be different).
Of course if you didn't like this feature, you could always use variables you define in an outer scope, such as you also do. =)
It would have been better if ob
had been called inner
, but anyway...
...is a new instance of the closure ("space in memory"?) created each time the outer function is called?
Yes and no. The function assigned to outer has a closure to the activation/variable object of the outer anonymous function. When outer is called, that object is placed on its scope chain and is used for identifier resolution. This is the same object each time (ECMA-262 doesn't say how this is to be done, but for all intents and purposes it's the same object).
The function assigned to ob[names[i++]]
has a closure to the instance of the activation/variable object created when outer was called and assigned the function. So each time outer is called, a new activation/variable object is created and each ob[..] function has a closure to a different outer activation/variable object but the same anonymous function activation/variable object.
I hope that makes sense.
Given that the result is
3 999
rather than
999 999
it appears as if ob.one points to a different closure instance to ob.two -each with its own value for val.
Both functions have the same anonymous function activation/variable object on their scope chain, so "share" a closure to obj, names, and i. But each as a unique instance of an outer activation/variable object on their scope chain so val will resolve to the same property name but on different objects (i.e. they don't share the same val property).
Maybe the following diagram of the scope chains makes sense:
ob.one -> outerA -> anonymous fn -> global
ob.two -> outerB -> anonymous fn -> global
So ob.one and ob.two have an outer instance on their scope chain, but they are different instances. They have the same anonymous function and global objects on their scope chains.
精彩评论