zoukankan      html  css  js  c++  java
  • Let和Const区别,详细版本

    let:声明的是变量
    1、不存在变量提升

    // var 的情况
    console.log(foo); // 输出undefined
    var foo = 2;
    
    // let 的情况
    console.log(bar); // 报错ReferenceError
    let bar = 2;

    上面代码中,变量foo用var声明,会发生变量提升,即脚本开始运行时,变量foo已经存在了,但是没有值,所以会输出undefined。变量用let声明,不会发生变量提升。这表示在声明它之前,变量bar是不存在的,这时如果用到他,就会抛出一个错误。

    2、暂时性死区,先声明在使用

    var tmp = 123;
    
    if (true) {
    tmp = 'abc'; // ReferenceError
    let tmp;
    }

    上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值报错,先声明再使用。

    3、不允许重复声明

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

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

    4、块级作用域

    ES5只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。

    第一种场景,内层变量可能会覆盖外层变量

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

    上面代码,if代码块的外部使用外层的tmp变量,内部使用内层的tmp变量。但是,函数f指向后,结果输出undefined,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。

    第二种场景,用来计数的循环变量泄露为全局变量。

    var s = 'hello';
    
    for (var i = 0; i < s.length; i++) {
    console.log(s[i]);
    }
    
    console.log(i); // 5

    上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄漏成了全部变量。

    ES6的块级作用域,let实际上为javascript新增的块级作用域。

    function f1() {
    let n = 5;
    if (true) {
    let n = 10;
    }
    console.log(n); // 5
    }

    上边代码,有两个代码块,都声明了变量n,运行后输出5。这表示外层代码块不受内层代码块的影响。如果两次都使用var定义变量n,最后输出的值才是10。

    ES6 允许块级作用域的任意嵌套。

    {{{{{let insane = 'Hello World'}}}}};

    const:常量

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

    const的作用域与let命令相同:只在声明所在的块级作用域内有效

    const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。

    const声明的常量,也与let一样不可重复声明。

    const foo = {};
    
    // 为 foo 添加一个属性,可以成功
    foo.prop = 123;
    foo.prop // 123
    
    // 将 foo 指向另一个对象,就会报错
    foo = {}; // TypeError: "foo" is read-only

    上面代码中,常量foo储存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把foo指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性

    ES6 声明变量的六种方法
    ES5 只有两种声明变量的方法:var命令和function命令。ES6 除了添加let和const命令,后面章节还会提到,另外两种声明变量的方法:import命令和class命令。所以,ES6 一共有 6 种声明变量的方法。

    let和const的相同点:
    ① 只在声明所在的块级作用域内有效。

    ② 不提升,同时存在暂时性死区,只能在声明的位置后面使用。

    ③ 不可重复声明。

    let和const的不同点:
    ① let声明的变量可以改变,值和类型都可以改变;const声明的常量不可以改变,这意味着,const一旦声明,就必须立即初始化,不能以后再赋值

    const i ; // 报错,一旦声明,就必须立即初始化
    const j = 5;
    j = 10; // 报错,常量不可以改变

    ② 数组和对象等复合类型的变量,变量名不指向数据,而是指向数据所在的地址。const只保证变量名指向的地址不变,并不保证该地址的数据不变,所以将一个复合类型的变量声明为常量必须非常小心。

    const arr = [];
    // 报错,[1,2,3]与[]不是同一个地址
    arr = [1,2,3];
    const arr = [];
    // 不报错,变量名arr指向的地址不变,只是数据改变
    arr[0] = 1;
    arr[1] = 2;
    arr[2] = 3;
    console.log(arr.length); // 输出:3

    若想让定义的对象或数组的数据也不能改变,可以使用object.freeze(arr)进行冻结。冻结指的是不能向这个对象或数组添加新的属性,不能修改已有属性的值,不能删除已有属性。

    const arr = [];
    Object.freeze(arr);
    // 不报错,但数据改变无效
    arr[0] = 1;
    arr[1] = 2;
    arr[2] = 3;
    console.log(arr.length); // 输出:0
  • 相关阅读:
    Android基础之项目结构分析
    串口调试,提示the given port name does not start with COM/com异常解决办法,,发现是打印机在搞怪
    C# 通过URL获取图片并显示在PictureBox上的方法
    学习资料集合
    C#语音朗读文本 — TTS的实现
    SQL SERVER 2008安装错误(is not a valid login or you do have permission)
    函数调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。
    SerialPort使用
    Javascript函数的几种写法
    JS验证图片格式和大小并预览
  • 原文地址:https://www.cnblogs.com/hy96/p/12955558.html
Copyright © 2011-2022 走看看