This is an adaptation of what you'd find in john resig's Learning Advanced Javascript app.
var math = {
fact: function fact(n){
return n > 0 ? n * fact(n-1): 1;
},
fact1: function (n) {
return n > 0? n * math.fact1(n-1) : 1;
}
};
console.log(math.fact(5)); // 120
console.log(math.fact1(5)); // 120
var o = {
x: math.fact,
y: math.fact1
};
math = {};
console.log(o.x === undefined); // false
console.log(o.y === undefined); // false
console.log(o.x(5)); // 120
console.log(o.y(5)); // Uncaught TypeError: math.fact1 is not a function
One would expect ox(5)
should throw an error, but it executes. Why?
When an object literal expression is evaluated, the expression to the right of each colon is evaluated and assigned to the specified property.
So when this executes:
var o = {
x: math.fact,
y: math.fact1
};
the expression math.fact
is evaluated, and the result is the function that math.fact
is referring to at that time .
The same goes for math.fact1
.
So even if you reassign the math
variable with math = {}
. ox
will continue to refer to that function. The o
object has no knowledge of the math
variable.
oy(5)
throws an error has to do with closures.
oy
refers to this function:
function (n) { return n > 0? n * math.fact1(n-1) : 1; }
You can see here that it uses the math
variable . Even if you reassign the math
variable, this function will continue to refer to the variable itself.
When you call oy(5)
, the function executes, but when it tries to call math.fact(n-1)
, that fails, because math
no longer has a property called fact
.
ox
does not have the problem that oy
has.
It is a named function, and therefore is able to continue to call itself even after math
is reassigned.
I don't understand why you would expect an error on ox
.
At the start, when we define math = { ... }
, we have two functions.
The first function is referenced both by its name fact
, and by the object property math.fact
The second function is anonymous, and is referenced only by math.fact1
We then "copy" the functions into o
. At this point, the first function is referenced by all of fact
, math.fact
and ox
, while the second function is referenced by math.fact1
and oy
.
We then destroy the math
object by replacing it with a new, empty object. At this point, the first function is referenced by fact
and ox
, and the second only by oy
.
Now we actually call the functions. ox
contains a recursive call to fact
, which is very clearly still defined as that function. However, oy
contains a recursive call to math.fact1
, which we destroyed, hence an error there.
This has nothing to do with... well, anything of interest. The function that names something that still exists continues to work, while the function that names something that doesn't exist any more fails.
I mean... duh...
ox
is a reference to a function (object). Because of this reference, the fact function will keep existing after the math object has been reset (objects only get garbage collected when no reference to them exist anymore).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.