• ES6 学习笔记


    let 和 const 命令


    学习资料:ECMAScript 6 入门

    let

    • 所声明的变量,只在let命令所在的代码块内有效。用途:循环计数器。

    如果使用var,只有一个全局变量i:

        var a = [];
        for (var i = 0; i < 10; i++) {
                a[i] = function () {
                        console.log(i);
                };
        }
        a[6](); // 10
    

    如果使用let,声明的变量仅在块级作用域内有效,JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算:

        var a = [];
        for (let i = 0; i < 10; i++) {
                a[i] = function () {
                        console.log(i);
                };
        }
        a[6](); // 6
    

    设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域:

        for (let i = 0; i < 3; i++) {
                let i = 'abc';
                console.log(i);
        }
        // abc
        // abc
        // abc
    
    • 不存在变量提升

    let所声明的变量一定要在声明后使用:

        // var 的情况
        console.log(foo); // 输出undefined
        var foo = 2;
    
        // let 的情况
        console.log(bar); // 报错ReferenceError
        let bar = 2;
    
    • 暂时性死区

    只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。所以需要先声明再使用:

        var tmp = 123;
    
        if (true) {
                tmp = 'abc'; // ReferenceError
                let tmp;
        }
    
        if (true) {
                // TDZ开始
                tmp = 'abc'; // ReferenceError
                 console.log(tmp); // ReferenceError
    
                let tmp; // TDZ结束
                console.log(tmp); // undefined
    
                tmp = 123;
                console.log(tmp); // 123
        }
    

    隐蔽的死区:

        function bar(x = y, y = 2) {
                return [x, y];
        }
    
        bar(); // 报错
    
    • 不允许重复声明

    let不允许在相同作用域内,重复声明同一个变量。

        // 报错
        function func() {
                let a = 10;
                var a = 1;
        }
    
        // 报错
        function func() {
                let a = 10;
                let a = 1;
        }
    
        function func(arg) {
                let arg; // 报错
        }
    
        function func(arg) {
                {
                        let arg; // 不报错
                }
        }
    

    块级作用域

    • ES5中没有块级作用域

    ES5中没有块级作用域,内层变量可能会覆盖外层变量:

        var tmp = new Date();
    
        function f() {
                console.log(tmp);
                if (false) {
                        var tmp = 'hello world';
                }
        }
    
        f(); // undefined
    

    ES5中没有块级作用域,用来计数的循环变量泄露为全局变量:

        var s = 'hello';
    
        for (var i = 0; i < s.length; i++) {
                console.log(s[i]);
        }
    
        console.log(i); // 5
    
    • ES6 的块级作用域

        function f1() {
                let n = 5;
                if (true) {
                        let n = 10;
                }
                console.log(n); // 5
        }
      
    • 块级作用域与函数声明

    ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。但在浏览器的 ES6 环境中,块级作用域内声明的函数,行为类似于var声明的变量。

        // 浏览器的 ES6 环境
        function f() { console.log('I am outside!'); }
    
        (function () {
                if (false) {
                // 重复声明一次函数f
                function f() { console.log('I am inside!'); }
                }
    
                f();
        }());
        // Uncaught TypeError: f is not a function
    

    考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。

        // 函数声明语句
        {
                let a = 'secret';
                function f() {
                        return a;
                }
        }
    
        // 函数表达式
        {
                let a = 'secret';
                let f = function () {
                        return a;
                };
        }
    

    ES6 的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错。

        // 不报错
        'use strict';
        if (true) {
                function f() {}
        }
    
        // 报错
        'use strict';
        if (true)
                function f() {}
    

    const 命令

    const声明一个只读的常量。一旦声明,常量的值就不能改变。

    const一旦声明变量,就必须立即初始化,不能留到以后赋值。

    与let类似,只在声明所在的块级作用域内有效。声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。不可重复声明。

    const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。

    如果真的想将对象冻结,应该使用Object.freeze方法。

        const foo = Object.freeze({});
    
        // 常规模式时,下面一行不起作用;
        // 严格模式时,该行会报错
        foo.prop = 123;
    

    除了将对象本身冻结,对象的属性也应该冻结。下面是一个将对象彻底冻结的函数。

        var constantize = (obj) => {
                Object.freeze(obj);
                Object.keys(obj).forEach( (key, i) => {
                        if ( typeof obj[key] === 'object' ) {
                                constantize( obj[key] );
                        }
                });
        };
    

    顶层对象的属性

    var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。

    垫片库system.global可以在所有环境拿到global。

        // CommonJS 的写法
        var global = require('system.global')();
    
        // ES6 模块的写法
        import getGlobal from 'system.global';
        const global = getGlobal();
    
  • 相关阅读:
    TensorFlow中使用GPU
    C++内存管理与注意事项
    深入理解Transformer及其源码
    Dropout原理与实现
    指针生成网络(Pointer-Generator-Network)原理与实战
    深度学习中的优化算法总结
    Hadoop伪分布式搭建
    集成学习总结
    模型评估
    基于Spring AOP实现的权限控制
  • 原文地址:https://www.cnblogs.com/renleimlj/p/7766006.html
Copyright © 2020-2023  润新知