" [JavaScript函数]在内部存储它们可能引用的在其封闭范围中定义的任何变量。"
如何确定这组变量是什么?
例如, Effective JavaScript 中的David Herman给出了这个函数(和闭包):
function sandwichMaker() {
var magicIngredient = "peanut butter";
function make(filling) {
return magicIngredient + " and " + filling;
}
return make;
}
var f = sandwichMaker();
document.writeln("<p>" + f("jelly") + "</p>");
document.writeln("<p>" + f("bananas") + "</p>");
document.writeln("<p>" + f("marshmallows") + "</p>");
当然, magicIngredient 是make()可以访问的变量,但还有什么呢?如果sandwichMaker本身在一个函数内怎么办?然后是全局变量。在当前范围内查找相关值时查看的函数是什么?
答案 0 :(得分:1)
如果sandwichMaker本身属于一个函数,该怎么办?然后是全局变量。
是的,来自父函数的所有变量都是可访问的(如果它们没有被遮蔽)。而最高范围的函数则继承自全局范围。
在当前范围内查找相关值时查看的函数是什么?
您可以使用调试器进行检查。在debugger;
中插入make
语句,然后执行它并查看您的devtools。你会看到这样的东西:
Scope Chain
0. make (currently executed):
this: (+)Window
arguments: (+)Arguments
filling "jelly"
1. sandwichMaker:
arguments: (+)Arguments
magicIngredient: "peanut butter"
make: (+)Function
Global
AnonXMLHttpRequest: …
ApplicationCache: …
Array: …
…
另请查看这篇精彩的文章:http://dmitrysoshnikov.com/ecmascript/es5-chapter-3-2-lexical-environments-ecmascript-implementation/
Chrome Devtools的示例视图:
答案 1 :(得分:1)
JavaScript使用功能范围。这很容易理解 - 在函数中声明的任何东西都具有该函数的范围以及任何更高的范围。
闭包可以被认为是两个被组合在一起的东西:特定的范围,和特定的时间点(创建函数时)。
当然,magicIngredient是make()可以访问的变量,但是什么 别的是?
创建时make
范围内可访问的任何内容。这包括make
函数中的所有变量以及任何更高的范围。 make的范围被称为封闭在创建时存在的范围,始终允许其访问magicIngredient
。
如果sandwichMaker本身属于一个函数,该怎么办?
然后make
也可以访问该范围(因为它在创建make
时存在)。
然后有全局变量。它看起来的功能是什么? 对于当前范围内的相关值?
解释器将在当前执行的范围中搜索任何引用的变量。如果它找不到它们,它将在下一个更高的范围内查找。它会继续越来越高,直到找到变量或用完范围(全局范围是最高的,也就是浏览器中运行的javascript的window
对象)。
一个相关的概念是 shadowing - 两个变量在父/子范围中可以具有相同的名称,孩子被称为“影子”父母,因为它将优先。请注意,这是一种不好的做法。
了解闭包和作用域的最简单方法是了解简单的工厂模式,例如this one。创建并返回内部函数时,它会在该时间点绑定到该作用域,并且即使在值不再存在之后也会继续警告正确的值。
希望这有所帮助 - 很多问题都塞进了一个问题:)
答案 2 :(得分:0)
假设上面function sandwichMaker()
定义了一个变量......
var something = 'something';
function sandwichMaker () {
...
您可以在something
内和sandwichMaker()
内访问make()
。
可以从函数中访问外部变量。如果您要在var something = 'something else'
内设置make()
,那么您将在var something
函数本身内隐藏外部make()
。但是,您只需设置something = 'something else'
,该值就会在所有范围内更改。如果再次声明该变量,它只会隐藏该值。