闭包 - 使用后的可变更改

时间:2017-10-24 20:05:45

标签: javascript closures

我正在阅读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?不应该通过值类型的原语?我也不认为作业被悬挂,只是声明,很丢失。

4 个答案:

答案 0 :(得分:1)

来自the article you linked

  

原因是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位于词汇范围内,而不是封闭的局部变量,makeFuncmakeFunc2都会在全局范围内操纵相同的值,这意味着重置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将从方法范围内更新为MozillamakeFunc()然后返回函数displayName(),而不触及/更新testtest仅在声明var myFunc = displayName() // return value of makeFunc()后才会更新。

在声明test后更改myFunc()的值会改变console.log()的{​​{1}}值。

test