我正在阅读MDN上的闭包,我在下面的代码中无法理解:
var test = 1;
function makeFunc() {
var name = 'Mozilla';
function displayName() {
alert(name + ' ' + test);
}
return displayName;
}
//Create myFunction - test should still be set to 1 at this point
var myFunc = makeFunc();
test = 99999;
myFunc();
在Mozilla 99999
分配Mozilla 1
时创建函数时,为什么要test
而不是1
?不应该通过值类型的原语?我也不认为作业被悬挂,只是声明,很丢失。
答案 0 :(得分:1)
原因是JavaScript中的函数形成闭包。闭包是函数和声明该函数的词法环境的组合。此环境由创建闭包时在范围内的任何局部变量组成。
此处,name
已关闭:它是创建函数时的局部变量。虽然它不是一个完美的类比,你可以把它想象成displayName
函数有一个指向堆栈框架的内部指针,其中包含定义函数时所有的局部变量。如果你传递name
,你可以看到它被保留。
var test = 1;
function makeFunc(name) {
function displayName() {
alert(name + ' ' + test);
}
return displayName;
}
//Create myFunction - test should still be set to 1 at this point
var myFunc = makeFunc("one");
var myFunc2 = makeFunc("two");
test = 99999;
myFunc(); // combines closed-over name "one" with lexical scope test 99999
myFunc2(); // combines closed-over name "two" with lexical scope test 99999

由于test
位于词汇范围内,而不是封闭的局部变量,makeFunc
和makeFunc2
都会在全局范围内操纵相同的值,这意味着重置test
即使您已经创建了闭包,也可以操纵输出。
答案 1 :(得分:0)
makeFunc
本身返回一个仅在赋值test = 9999;
后调用的函数。变量test
可从'外部'上下文(通过关闭)。
答案 2 :(得分:0)
闭包不仅在创建时捕获test
的快照,而且还捕获整个变量本身。这意味着无论何时调用函数myFunc
,它都会打印调用它时test
的值,不时test
的值关闭已经创建。
换句话说,在闭包内部,test
仍然是变量,而不是值。这意味着它可以根据需要进行更改和操作,使用它的任何内容都可以看到这些更改。
因此,对于您的代码,只要在最后一行调用myFunc()
,运行时就会评估表达式name + ' ' + test
,并且由于测试现在是99999
,所以'你得到了什么。
答案 3 :(得分:0)
这是因为当test
返回makeFunc()
时displayName
未更新。
查看我从方法name
范围中删除的makeFunc()
到全局范围。执行makeFunc()
后,name
将从方法范围内更新为Mozilla
。 makeFunc()
然后返回函数displayName()
,而不触及/更新test
。 test
仅在声明var myFunc = displayName() // return value of makeFunc()
后才会更新。
在声明test
后更改myFunc()
的值会改变console.log()
的{{1}}值。
test