微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

JavaScript闭包与匿名函数

如何解决JavaScript闭包与匿名函数

在JavaScript中所有的功能关闭在这个解释后但是,我们只对确定这些功能的子集感兴趣,这从理论上讲是很[有趣的。此后,除非另有说明,否则对闭包一词的任何引用都将指代此功能子集。

闭包的简单说明:

  1. 发挥作用。我们称它为F。
  2. 列出F的所有变量。
  3. 变量可以有两种类型:
    1. 局部变量(绑定变量)
    2. 非局部变量(自由变量)
  4. 如果F没有自由变量,则它不能是闭包。
  5. 如果F具有任何自由变量(在F 父范围中定义),则:
    1. 必须有其中的F只有一个父范围 自由变量绑定。
    2. 如果从 ***
    3. 自由变量称为闭包F的升值。

现在,让我们用它来找出谁使用闭包,谁不使用闭包(为便于说明,我将函数命名为):

for (var i = 0; i < 10; i++) {
    (function f() {
        var i2 = i;
        setTimeout(function g() {
            console.log(i2);
        }, 1000);
    })();
}

在以上程序中,有两个功能fg。让我们看看它们是否为闭包:

对于f

  1. 列出变量:
    1. i2是 变量。
    2. i一个 变量。
    3. setTimeout一个 变量。
    4. g是 变量。
    5. console一个 变量。
  2. 查找每个自由变量绑定到的父范围:
    1. i被 到了全球范围。
    2. setTimeout被 到了全球范围。
    3. console被 到了全球范围。
  3. 功能在哪个范围内 ?在 。
    1. 因此i没有 通过f
    2. 因此setTimeout没有 通过f
    3. 因此console没有 通过f

因此,该功能f不是闭包。

对于g

  1. 列出变量:
    1. console一个 变量。
    2. i2一个 变量。
  2. 查找每个自由变量绑定到的父范围:
    1. console被 到了全球范围。
    2. i2被 到的范围f
  3. 功能在哪个范围内 ?的 。
    1. 因此console没有 通过g
    2. 因此i2被 通过g

因此,该功能g是用于自由变量的封闭i2(这是用于的upvalue g) 它的 从内setTimeout

对您不利: 您的朋友正在使用闭包。内部函数一个闭包。

for (var i = 0; i < 10; i++) {
    setTimeout((function f(i2) {
        return function g() {
            console.log(i2);
        };
    })(i), 1000);
}

在以上程序中,有两个功能fg。让我们看看它们是否为闭包:

对于f

  1. 列出变量:
    1. i2是 变量。
    2. g是 变量。
    3. console一个 变量。
  2. 查找每个自由变量绑定到的父范围:
    1. console被 到了全球范围。
  3. 功能在哪个范围内 ?在 。
    1. 因此console没有 通过f

因此,该功能f不是闭包。

对于g

  1. 列出变量:
    1. console一个 变量。
    2. i2一个 变量。
  2. 查找每个自由变量绑定到的父范围:
    1. console被 到了全球范围。
    2. i2被 到的范围f
  3. 功能在哪个范围内 ?的 。
    1. 因此console没有 通过g
    2. 因此i2被 通过g

因此,该功能g是用于自由变量的封闭i2(这是用于的upvalue g) 它的 从内setTimeout

对您有好处: 您正在使用闭包。内部函数一个闭包。

因此,您和您的朋友都在使用闭包。别吵了 我希望我清除了闭包的概念以及如何为你们两个人识别它们。

关于为什么所有函数关闭的简单说明(点数@Peter):

首先让我们考虑以下程序(它是control):

lexicalScope();



function lexicalScope() {

    var message = "This is the control. You should be able to see this message being alerted.";



    regularFunction();



    function regularFunction() {

        alert(eval("message"));

    }

}
  1. 我们知道,无论lexicalScoperegularFunction不封闭 。
  2. 当我们执行程序时, message收到警告, regularFunction它不是闭包的(即它可以访问其父作用域中的 变量-包括message)。
  3. 当我们执行程序时, 到message确实确实有警报。

接下来让我们考虑以下程序(这是替代程序):

var closureFunction = lexicalScope();



closureFunction();



function lexicalScope() {

    var message = "This is the alternative. If you see this message being alerted then in means that every function in JavaScript is a closure.";



    return function closureFunction() {

        alert(eval("message"));

    };

}
  1. 我们知道,这只是 *
  2. 当我们执行程序时, 我们希望* message不会 closureFunction闭包而收到警告(即,在 它只能访问其所有 (请参见此答案)-不包括)。 *message
  3. 当我们执行程序时, 到message实际上正在被警告。

我们从中得出什么呢?

  1. JavaScript解释器对待闭包的方式与对待其他函数的方式没有区别。
  2. 每个功能都带有其作用域链。闭包没有 引用环境。
  3. 闭包就像其他函数一样。当在它们所属的范围 之外* 的范围中 它们时,我们只称它们为闭包, 这是一个有趣的情况。 ***

解决方法

我的一个朋友和我目前正在讨论JS中的闭包和不闭包。我们只想确保我们正确理解它。

让我们来看这个例子。我们有一个计数循环,希望延迟在控制台上打印计数器变量。因此,我们使用setTimeout闭包
捕获计数器变量的值,以确保其不会打印N倍于值N的值。

没有 闭包 或接近 闭包 的错误解决方案是:

for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);
    },1000);
}

当然,它将i在循环后输出10倍的值,即10。

所以他的尝试是:

for(var i = 0; i < 10; i++) {
    (function(){
        var i2 = i;
        setTimeout(function(){
            console.log(i2);
        },1000)
    })();
}

按预期打印0到9。

我告诉他,他并没有使用 闭包 捕获i,但他坚持认为自己是。我通过将for循环体放在另一个循环中(将他的匿名函数传递给),再次打印10次10
证明了他没有使用 闭包 。如果我将他的函数存储在a中并在循环 执行它,也打印10次10​​,则同样适用。所以我的观点是 他并没有真正
捕获 的值 ,因此他的版本 不是 闭包的。setTimeout``setTimeout``var __i

我的尝试是:

for(var i = 0; i < 10; i++) {
    setTimeout((function(i2){
        return function() {
            console.log(i2);
        }
    })(i),1000);
}

所以我捕获了ii2在闭包中命名),但是现在我 返回了 另一个函数并传递了它。
就我而言,传递给setTimeout的函数实际上捕获了i

现在谁在使用闭包,谁没有?

请注意,这两种解决方案在控制台上都延迟输出0到9,因此它们可以解决原始问题,但是我们想了解这两种解决方案中的哪一种 使用闭包 来完成此任务。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。