【问题标题】:Javascript - can't understand closureJavascript - 无法理解闭包
【发布时间】:2016-01-30 01:01:40
【问题描述】:

我有以下代码:

function bird(type) {
    return function (whattosay) { //return the whole function
        console.log (type + ' ' + whattosay)
    }

}

var birdRef = bird('blackbird'); 
birdRef('singing in the dead of night');

var secondRef = bird('whitebird');

birdRef('singing after that night');

我正在尝试熟悉两个概念,闭包和作用域链。 好吧,在我的第一个birdRef 中,我返回一个新的函数对象,然后在该行之后调用它。最后,我在控制台中看到“黑鸟在深夜唱歌”。我知道为了找到鸟类型 var,闭包给你一个对父级的引用,它有点在作用域链中寻找那个 var 并最终找到它,所以我们看到了鸟的类型。

那么你有这个:

var secondRef = bird('whitebird');

已经传递了一个新参数,所以现在 Bird 函数中的 var "type" 从 blackbird 更改为 whitebird。

现在我回到我之前创建的函数birdRef,我不明白的是,接下来会发生什么:

birdRef('singing after that night');

我得到“那晚之后黑鸟在唱歌”,而不是白鸟。好吧,如果我没记错的话,birdRef函数不是到它的父函数bird,并读取更新的bird变量的类型(我的意思是他在本地环境中找不到那个var,所以他查看外部环境,发现 var "type")?

对不起,如果我不了解,因为我是新手,感谢您抽出宝贵时间。

【问题讨论】:

  • 不,每个函数调用都会创建一个带有不同 type 变量的新上下文(环境)。 birdRef 和 secondRef 是两个不同的函数对象,它们关闭了两个不同的变量。
  • 就好像,每次鸟函数调用都会创建一个适合调用者的新鸟函数?
  • 正确,每个bird()返回一个新函数(代码相同但上下文不同)
  • 你能告诉我这或多或少会发生什么吗? pasteboard.co/1Kh7a4MM.jpg
  • 那个链接是404,所以我什么都说不出来

标签: javascript scope closures chain


【解决方案1】:

第二次你实际上调用了第一个闭包的结果。

下面一行:

birdRef('singing after that night');

应该是:

secondRef('singing after that night');

我在下面包含了一个工作演示。

function bird(type) {
    return function (whattosay) { //return the whole function
        console.log (type + ' ' + whattosay)
    }

}

var birdRef = bird('blackbird'); 
birdRef('singing in the dead of night');

var secondRef = bird('whitebird');
secondRef('singing after that night');
// ^^ secondRef instead of birdRef

// Test is again.
birdRef('singing in the dead of night');
secondRef('singing after that night');

因为type 是在函数调用的词法范围内定义的,所以在该词法范围之外无法访问它。如上所示,除非变量在定义它的词法范围内被修改,否则它不能被访问或修改。

【讨论】:

  • 我故意放了第二次birdRef,是为了看看鸟的类型是否因为上一行代码secondRef而改变。这个想法是为了看看它是否会影响 birdRef 函数,因为 birdRef 沿着作用域链向上并试图找到最近被 secondRef 更改的“类型”变量。
  • 不,它不会沿着作用域链上升,因为类型是在由分配给 bird 关键字的外部函数声明创建的词法作用域内声明的。因为每次调用 bird 时,它都会创建一个新的词法范围,然后在其中创建返回的函数。
  • 我写了a demo 希望能给你一个更好的理解。基本上,当您将关键字添加到函数的参数列表时,该关键字将使用函数调用中传递的值标识在以下范围内可访问的变量。这就像您在函数范围内使用 var 关键字定义变量并为其分配静态值一样。
  • 我唯一能理解的是,每次调用都会创建一个新的鸟函数,并且计算机不会以某种方式覆盖并且可以引用它们在内存中的点。我认为范围链 = 词法环境...
  • 与其说是创建了一个新的bird 函数,不如说是每次调用bird 时都会创建一个新的词法范围,在其中“构建”一个新函数并返回该函数。返回的函数引用在声明它的词法范围内运行。用更人性化的话来说,一个函数是在说“每次使用这个关键字时,根据提供的参数执行这组任务”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-11
  • 1970-01-01
  • 2013-03-25
  • 2012-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多