关闭误解

时间:2016-04-05 18:45:36

标签: javascript closures

我以为我理解了闭包,但我猜不是。这是一个代码示例,显示了我遇到的问题。我希望代码可以打印出文字'到控制台。

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 个答案:

答案 0 :(得分:3)

这里的问题不是闭包的结果,因为它是范围...而且我更倾向于考虑父/子关系中的JavaScript范围。

任何作用域实体(例如函数)都可以访问其继承的“父”作用域中定义的内容(可见性向上移动) - 但“父”作用域不能看到“子”作用域内部,以及相同作用域的子作用域看不到彼此。

enter image description here

上面的图片是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