美文网首页
ES6(一)块级绑定

ES6(一)块级绑定

作者: 蒋小花_4b6c | 来源:发表于2020-04-15 19:01 被阅读0次

    JS中使用变量绑定数据,统一个变量不同的声明方式输出不同的值,那末我们一起来看看吧,Let's go!

     1.块级绑定

     var let const

    首先解释一个概念:

    变量提升Hosting:无论其实际声明位置在何处,都会被视为声明于所在函数的顶部,如果声明不在任意函数内,则视为在全局作用域的顶部。

    初学需要花点儿时间来习惯变量提升,如果不理解这种思想可能会导致bug

    因此引入块级作用域,让变量的生命周期更可控。

    咱们来做道题测试测试吧

    () => {

        var a = 0;

        if(true) {

            a = 1;

            function a() {};

            a = 21;

            console.log('in', a);

        }

        console.log('out', a);

    }

    正确答案是: in 21, out 1

    详细讲解请看这里: https://mp.weixin.qq.com/s/UNYO-OsIul8_gUdcghIBwQ

    块级作用域

     让所声明的变量在指定块的作用域外无法被访问。块级作用域(又被称为词 法作用域)在如下情况被创建:

        1.  在一个函数内部

        2.  在一个代码块(由一对花括号包裹)内部

    let

    基本可以代替var,作用域在当前的代码块中

    一对{}里面使用let声明变量,下面行的代码就可以使用此变量了

    如果需要整个{}内都可以使用A变量,则需要把A变量放到{}顶部

    function getValue(condition) {

        if(condition) {

            let value = 'blue';

            console.log(value); // return value;

        } else {

            console.log(value);

            return null;

        }

        console.log(value);

    }

    在这个例子中value 只在if{}里面才生效,其他地方没有value

    TIPS: 

    1.禁止重复声明同一变量

    () => {

        var value = 1;

        let value = 2; // 错误

    }

    function change(condition) {

        var value = 1;

        if(condition) {

            let value = 2;

            console.log(value); // return  value;

        } else {

            return null;

        }

        console.log(value);

    }

    const 常量

    const用来声明常量constant,常量初始化之后不能被改变,且必须在声明时就初始化。

    const maxItems = 30;

    const minItems; // 语法错误未初始化

    let const 都是块级声明,语句块外部无法访问,变量也不会提升。

    if (condition) {

        const maxItems = 5;

        // 其他代码

        }

        // maxItems 在此处无法访问

    常量 maxItems 在 if 语句内被声明,在if{}外部无法被访问

    var message = "Hello!";   let age = 25;

    // 二者均会抛出错误

    const message = "Goodbye!";    const age = 30;

    变量已经被声明就不得用const再次声明。

    const maxItems = 5;

    maxItems = 6;      // 抛出错误

    const声明的常量不得再次赋值。

      const 声明会阻止对于变量绑定与变量自身值的修改,这意味着 const 声明并不会阻止对 变量成员的修改。

    const person = {name: "Nicholas"

    };

    // 工作正常

    person.name = "Greg";

    // 抛出错误

    person = {

    name: "Greg"

    };

    不能修改常量本身的值,但可以修改常量对象的属性值。

    补充一个概念:‘暂时性死区’

    if (condition) {

        console.log(typeof value);  // 引用错误

    let value = "blue";

    }

    此处的 value 变量使用了 let 进行定义与初始化,但该语句永远不会被执行,

    因为声明之 前的那行代码抛出了一个错误。

    出现该问题是因为:value  位于暂时性死区

    temporal dead zone , TDZ )内。

    该名称并未在 ECMAScript 规范中被明确命 名,但经常被用于描述 let 或 const 声明的变量为何在声明处之前无法被访问。

    console.log(typeof value); // "undefined"

    if (condition) {

        let value = "blue";

    }

    当 typeof 运算符被使用时, value 并没有在暂时性死区内,因为这发生在定义 value 变 量的代码块外部。这意味着此时并没有绑定 value  变量,而 typeof 仅单纯返回了

      "undefined" 。

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

        process(items[i]);

    }

    // i 在此处仍然可被访问

    console.log(i);

    for (let i = 0; i < 10; i++){process(items[i]);

    }

    // i 在此处不可访问,抛出错误

    console.log(i);

    变量 i  仅在 for  循环内部可用,一旦循环结束,该变量在任意位置都不可访问。

     

    IIFE

    var funcs = [];

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

    funcs.push(function() { console.log(i); });

    }

    funcs.forEach(function(func) {func(); // 输出数值 "10" 十次

    });

    你原本可能预期这段代码会输出 0 到 9 的数值,但它却在同一行将数值 10 输出了十次。这是 因为变量 i 在循环的每次迭代中都被共享了,意味着循环内创建的那些函数都拥有对于同一 变量的引用。在循环结束后,变量 i 的值会是 10 ,因此当 console.log(i) 被调用时, 每次都打印出10 。

    为了修正这个问题,开发者在循环内使用立即调用函数表达式(IIFEs),以便在每次迭代中 强制创建变量的一个新副本,示例如下:

    var funcs = [];

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

     funcs.push((function(value) {

        return function() {

        console.log(value);

    }

    }(i)));

    }

    funcs.forEach(function(func) {func(); // 从 0 到 9 依次输出

    });

    这种写法在循环内使用了 IIFE 。变量 i 被传递给 IIFE ,从而创建了value 变量作为自身 副本并将值存储于其中。 value 变量的值被迭代中的函数所使用,因此在循环从 0 到9 的过 程中调用每个函数都返回了预期的值。幸运的是,使用 let 与 const 的块级绑定可以在 ES6 中为你简化这个循环。

    在循环内使用let声明

    var funcs = [];

    for (let i = 0; i < 10; i++) {funcs.push(function() {

    console.log(i);

    });

    }

    funcs.forEach(function(func) {func(); // 从 0 到 9 依次输出

    }

    在for-in中使用

    var funcs = [],object = {

    a: true,b: true,c: true

    };

    for (let key in object) {funcs.push(function() {

    console.log(key);

    });

    }

    funcs.forEach(function(func) {

    func();     // 依次输出 "a"、"b"、 "c"

    });

    但是注意不要使用const来声明:

    function getConst3() {

        var arr = [];

        for(const i = 0; i < 10; i++) {

            arr.push(function() {

                console.log(i);

            });

        }

        arr.forEach(item => {

            item();

        });

    }

    但是可以在for-in和for-of中使用const:

    for (const key in object) {funcs.push(function() {

        console.log(key);

    });

    }

    是因为,循环未每次迭 代创建了一个新的变量绑定,而不是试图去修改已绑定的变量的值

    使用var定义变量时变量时全局变量,可以通过window.变量来访问(变成window的一个属性 这是js的工作方式),那这就意味着var可能会重写其他的变量。

    使用let、const虽然会在全局创建新的绑定,但是不会覆盖全局对象的值,也不会有任何属性背添加到全局对象上。

    可以用以下代码测试看看:

    const RegExp = 'hi';

    console.log(RegExp, window.RegExp, RegExp === window.RegExp);

    var newWord = 'word';

    console.log(‘ newWord ’ in window, window.newWord);

    总结:

    1.可以尽量使用let代替var(默认情况下使用let),常量使用const。

    或者

    默认情况下使用const,当变量需要被修改的时候才用let。‘其理论依据是大部分 变量在初始化之后都不应当被修改,因为预期外的改动是 bug 的源头之一’

    2.let 与 const不会进行提升,并且 只会在声明它们的代码块内部存在。

    不能在变量声明位置之前访问 它们,即便使用的是typeof 这样的安全运算符

    3.块级绑定当前的最佳实践就是:在默认情况下使用 const ,而只在你知道变量值需要被更改 的情况下才使用 let 。

    相关文章

      网友评论

          本文标题:ES6(一)块级绑定

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