为什么命名的javascript函数会持续存在?

deo*_*oll 0 javascript closures function function-expression

这是对你在john resig的Learning Advanced Javascript应用程序中找到的内容的改编.

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
Run Code Online (Sandbox Code Playgroud)

人们会期望o.x(5)应该抛出错误,但它会执行.为什么?

JLR*_*she 5

评估对象文字表达式时,将评估每个冒号右侧的表达式并将其分配给指定的属性.

所以当执行时:

var o = {
    x: math.fact,
    y: math.fact1
};
Run Code Online (Sandbox Code Playgroud)

表达math.fact进行评价,其结果是,功能math.fact指的是在那个时候.

同样的道理math.fact1.

所以即使你重新分配math变量math = {}.o.x将继续参考该功能.该o对象没有的知识math变量.


o.y(5)抛出错误 的原因与闭包有关.

o.y 指的是这个功能:

function (n) {
     return n > 0? n * math.fact1(n-1) : 1;
}
Run Code Online (Sandbox Code Playgroud)

你可以在这里看到它使用math 变量.即使重新分配math变量,此函数也将继续引用变量本身.

当你调用时o.y(5),函数会执行,但是当它尝试调用math.fact(n-1)时,失败,因为math不再有一个被调用的属性fact.


o.x没有问题o.y.它是一个命名函数,因此即使在math重新分配后也能够继续调用它自己.