let & const —— ES6基础总结(二)

1,304 阅读4分钟

前言

在JS中,var早已深入人心,因此本文将不再赘述,仅在必要时拉出来溜溜。

声明方式 变量提升 暂时性死区 重复声明 可修改值 块级作用域 全局变量属于顶层对象
var
let
const 否(引用类型仅保证地址不被修改)

变量提升

    a   // a is not defined
    let a = 'a'
    
    b  // b is not defined
    const b = 'b'
    
    c   // undefined
    var c = 'c'

暂时性死区

在代码块内,使用letconst命令声明变量之前,该变量都是不可用的。

其本质是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

    typeof a    // a is not defined
    let a = 'a'
    
    typeof b    // b is not defined
    const b = 'b'
    
    typeof c    // "undefined"
    var c = 'c'

以下为几个比较隐蔽的死区:

  1. 赋值

    var a = a
    let b = b   // b is not defined
    
  2. 函数参数

    function foo(a = b, b = 2) {
      console.log([a, b])
    }
    foo()
    

重复声明

    let a = 'a1'
    let a = 'a2'    // Identifier 'a' has already been declared
    a   // a1
    
    const b = 'b1'
    const b = 'b2'  // Identifier 'b' has already been declared
    b   // b2
    
    var c = 'c1'
    var c = 'c2'
    c   // c2

修改值

    let a = 'a1'
    a = 'a2'    
    a   // a2
    
    const b = 'b1'
    b = 'b2'  // Assignment to constant variable
    b   // b1
    
    var c = 'c1'
    c = 'c2'
    c   // c2

const 引用类型仅保证引用地址不可修改

    const a = {
       a1: 1,
       a2: 2
    }
    a.a3 = 3
    a   // {a1: 1, a2: 2, a3: 3}

块级作用域

    {
        let a = 'a'     
        const b = 'b'   
        var c = 'c'
    }
    a   // a is not defined
    b   // b is not defined
    c   // c

全局变量不再属于顶层对象

顶层对象:浏览器中指window,Node中指global

    let a = 'a'
    window.a    // undefined 
    
    const b = 'b'
    window.b    // undefined 
    
    var c = 'c'
    window.c    // "c"

再也不用担心手抖修改了顶层对象~

解决的问题

  1. 内层变量覆盖外层变量;

  2. 用来计数的循环变量变为全局变量;

    1. 上面代码中,变量j是let声明的,当前的j只在本轮循环有效,所以每一次循环的j其实都是一个新的变量,那么如果每一轮循环的变量j都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量j时,就在上一轮循环的基础上进行计算。
    1. for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

  3. 闭包与垃圾回收;

    有块级作用域

    有块级作用域

    无块级作用域

    无块级作用域

  4. 不再需要使用立即执行函数,减少代码冗余提升可读性;

  5. 允许在块级作用域中声明函数,函数声明语句的行为类似于let;

    原来,如果改变了块级作用域内声明的函数的处理规则,显然会对老代码产生很大影响。为了减轻因此产生的不兼容问题,ES6 在附录 B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式

    1.允许在块级作用域内声明函数。

    2.函数声明类似于var,即会提升到全局作用域或函数作用域的头部。

    3.同时,函数声明还会提升到所在的块级作用域的头部。

    注意,上面三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作let处理。

参考

  1. ECMAScript 6 入门

  2. 你不知道的JavaScript(上)

小结

本文主要介绍了letconstvar定义变量的区别以及优点。推荐我用了两个月的时间才理解 let这篇文章,供大家思考。

之前声明变量只能使用varfunction,现在ES6添加了letconstimportclass4种方式(importclass 后续也会一一总结),所以现在总共有6种声明变量的方式。SO声明变量,请合理选择。

感谢阅读,如有问题,欢迎指正。

最最最最最后,在这四天的五一小长假里,为大家献上美景 —— 摩洛哥蓝色小镇🇲🇦祝大家五一愉快呦~

摩洛哥蓝色小镇