美文网首页
JavaScript——可变范围和关闭

JavaScript——可变范围和关闭

作者: 2o壹9 | 来源:发表于2020-01-11 19:45 被阅读0次

    在JavaScript中,您在使用变量之前先声明它们:var

    > var x;

    > x

    未定义

    > y

    ReferenceError:y未定义

    您可以使用一个var 语句来声明和初始化几个变量:

    var x = 1, y = 2, z = 3;

    但是我建议每个变量使用一个语句(原因在Syntax中进行了解释)。因此,我将前面的语句重写为:

    var x = 1;

    var y = 2;

    var z = 3;

    由于提升(请参见变量提升),通常最好在函数的开头声明变量。

    变量是函数范围的

    变量的范围始终是完整的功能(与当前块相反)。例如:

    function foo() {

        var x = -512;

        if (x < 0) {  // (1)

            var tmp = -x;

            ...

        }

        console.log(tmp);  // 512

    }

    我们可以看到变量tmp不限于从第(1)行开始的块。它存在直到函数结束。

    变量被吊起

    每个变量声明都是悬挂的:该声明将移至该函数的开头,但保留的赋值将保留。例如,请考虑以下函数中第(1)行中的变量声明:

    function foo() {

        console.log(tmp); // undefined

        if (false) {

            var tmp = 3;  // (1)

        }

    }

    在内部,前面的函数是这样执行的:

    function foo() {

        var tmp;  // hoisted declaration

        console.log(tmp);

        if (false) {

            tmp = 3;  // assignment stays put

        }

    }

    关闭

    每个功能 即使它离开了创建它的作用域,它仍然与围绕它的函数的变量保持联系。例如:

    function createIncrementor(start) {

        return function () {  // (1)

            start++;

            return start;

        }

    }

    从第(1)行开始的函数会离开其创建时所在的上下文,但仍保持与以下版本的实时连接start:

    > var inc = createIncrementor(5);

    > inc()

    6

    > inc()

    7

    > inc()

    8

    一个封闭的功能加上其周边范围的变量的连接。因此,createIncrementor()返回的是封闭。

    IIFE模式:引入新的范围

    有时您想引入一个新的 变量作用域-例如,防止变量成为全局变量。在JavaScript中,您不能使用块来这样做。您必须使用一个函数。但是,存在一种以块状方式使用功能的模式。它称为IIFE(立即调用的函数表达式,发音为“ iffy”):

    (function () {  // open IIFE

        var tmp = ...;  // not a global variable

    }());  // close IIFE

    确保完全按照显示的方式键入前面的示例(注释除外)。IIFE是定义后立即调用的函数表达式。在函数内部,存在新的作用域,以防止其tmp成为全局变量。有关IIFE的详细信息,请咨询通过IIFE引入新范围。

    IIFE用例:通过关闭无意间共享

    闭包保持它们与外部变量的连接,有时这不是您想要的:

    var result = [];

    for (var i=0; i < 5; i++) {

        result.push(function () { return i });  // (1)

    }

    console.log(result[1]()); // 5 (not 1)

    console.log(result[3]()); // 5 (not 3)

    第(1)行中返回的值始终是的当前值i,而不是创建函数时的值。循环完成后,i值为5,这就是数组中所有函数都返回该值的原因。如果希望第(1)行中的函数接收的当前值的快照,则i可以使用IIFE:

    for (var i=0; i < 5; i++) {

        (function () {

            var i2 = i; // copy current i

            result.push(function () { return i2 });

        }());

    }

    相关文章

      网友评论

          本文标题:JavaScript——可变范围和关闭

          本文链接:https://www.haomeiwen.com/subject/qcebactx.html