我以为我理解闭包但我猜不是 . 这是一个代码示例,显示了我遇到的问题 . 我希望代码能够将'text'打印到控制台 .
var inner = function() {
console.log(text);
};
var outer = function(cb) {
var text = 'text';
cb();
};
我使用内部函数作为cb运行外部函数 . 在这种情况下,我得到的var文本是未定义的 . 我认为由于js闭包,内部函数仍然会引用text变量 .
//Run outer with a cb of inner.
outer(inner);
尝试使用匿名函数作为cb并给出相同的文本未定义错误 .
//Anonymous
outer(function() {
console.log(text);
});
我在这里缺少什么想法?我在我的程序的其他方面使用闭包没有问题,但显然我不完全理解发生了什么 .
5 回答
这里的问题不是闭包的结果,因为它是范围...而且我更喜欢在父/子关系方面考虑JavaScript范围 .
任何作用域实体(例如函数)都可以访问其继承的“父”作用域中定义的内容(可见性向上移动) - 但“父”作用域不能看到“子”作用域内部,同一作用域的子作用不能看到内部另一个 .
上面的图片是Google图片中的通用和无耻窃取,但用于解释“A”是父作用域; “B”和“C”在父范围内定义 . “D”和“E”在“B”的范围内定义 - 因此“C”不能看到“D”或“E” .
在您的示例中,"parent"范围是定义这两个函数的上下文(可能是
window
) . 其中一个"children"方法的范围(上下文)中的任何内容都可以在其上方的作用域(上下文)中看到 defined - 因此outer()
中的代码知道inner()
存在(两者都在父作用域中定义),但是两种功能都不能看到对方内部存在的东西 . (注意:父作用域(大概是window
)也看不到每个函数内部的定义;它只知道存在的函数 . )但由于可见性仅向上移动,
inner()
内的范围不知道text
因为它是在outer()
内定义的 .text
未定义 - 这不是一个不将参数传递给回调的问题:在
outer
内调用cb
时没有(相关)闭包 .如果您在
outer
内创建了inner
,那么您将关闭text
,并且在调用inner
时会看到它的值 - 但您不是 .text
里面inner
是全球text
.闭包允许函数访问定义它们的作用域中的变量,而不是它们被调用的作用域 .
修改您的示例,以下将打印“已更改的文本” .
您还应该学习术语Lexical Scoping以了解情况 . 变量/函数的范围由其在源代码中的位置定义 .
在第二个/外部函数中声明函数然后从该函数返回(第二个/外部)时,将创建一个闭包 . 在您的情况下,
inner
函数未在outer
函数内声明 .您可以重新安排代码以形成一个闭包: