我以为我理解了闭包,但我猜不是。这是一个代码示例,显示了我遇到的问题。我希望代码可以打印出文字'到控制台。
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);
});
我在这里缺少什么想法?我在程序的其他方面使用闭包没有问题,但很明显我不完全理解发生了什么。
答案 0 :(得分:3)
这里的问题不是闭包的结果,因为它是范围...而且我更倾向于考虑父/子关系中的JavaScript范围。
任何作用域实体(例如函数)都可以访问其继承的“父”作用域中定义的内容(可见性向上移动) - 但“父”作用域不能看到“子”作用域内部,以及相同作用域的子作用域看不到彼此。
上面的图片是Google图片中的通用和无耻窃取,但用于解释“A”是父作用域; “B”和“C”在父范围内定义。 “D”和“E”在“B”的范围内定义 - 因此“C”不能看到“D”或“E”。
在您的示例中,“父”范围是定义这两个函数的上下文(可能是window
)。在其中一个“子”方法的范围(上下文)中的任何定义可以在其上方的范围(上下文)中看到已定义的内容 - 因此{ {1}}知道outer()
存在(两者都在父作用域中定义),但两个函数都不能看到另一个内部存在的内容。 (注意:父范围(可能是inner()
)也无法看到每个函数内部定义的内容;它只知道存在的函数。)
但由于可见性仅向上移动,window
内的范围不知道inner()
,因为它是在text
内定义的。
答案 1 :(得分:2)
text
未定义 - 这不是关闭问题,这是一个不将参数传递给回调的问题:
var outer = function(cb) {
var text = 'text';
cb(text); //note the parameter pass in here
};
outer(function(textParam) { //and now the callback passed in accepts a param
console.log(textParam) //name this param whatever you want!
});
答案 2 :(得分:1)
在cb
内拨打outer
时,没有(相关)关闭。
如果您在inner
内创建了 outer
,那么您将关闭text
,并且在调用inner
时会看到它的值} - 但你不是。
text
内的inner
是全球text
。
答案 3 :(得分:0)
闭包允许函数访问定义它们的作用域中的变量,而不是它们被调用的作用域。
修改您的示例,以下内容将打印"更改文本"。
var text = 'some text';
var inner = function() {
console.log(text);
};
text = 'changed text'
var outer = function(cb) {
cb();
};
outer(inner);
答案 4 :(得分:0)
您还应该学习术语Lexical Scoping以了解情况。变量/函数的范围由其在源代码中的位置定义。
在第二个/外部函数中声明函数然后从该函数返回(第二个/外部)时,会创建一个闭包。在您的情况下,inner
函数未在outer
函数内声明。
您可以重新安排代码以形成一个闭包:
function outer() {
var text = 'text';
function inner(){
console.log(text);
};
return inner;
}
var foo = outer();
foo(); // text