ES6学习笔记(二)--let和const

在这之前先了解什么是顶层对象:在浏览器里指的是window 在Node指的是global
因此 在es5中,全局对象总是能在顶层对象的属性中找到
因为顶层对象在任何一处都能读取,这样就造成了全局对象也处处能读取到而不小心被改写,不利于模块化开发
es6 中let const 的出现正是为了解决这种问题的
    window.global_a = 'a'
    var global_a = 'b'
    window.global_a // 'b'
    const global_b = 'const b'
    window.global_b = 'window b'
    window.global_b // 'window b'
关于let
let是es6新增的命令,用来声明变量,用法跟var类似,但是所声明的变量只在let命令所在的代码块内有效
   {
        let global_d = 'let d' 
        var global_e = 'var e'
        console.log(global_d) // 'let d'
          {
            let global_d = 'let d d d'
            console.log( '子作用域',global_d) // 子作用域 let d d d   子作用域是独立存在的,声明的变量不会覆盖父作用域的同名变量
           }
           console.log( '父作用域',global_d)

} // console.log(global_d) // 报错:global_d is not defined 且不继续往下执行 console.log(global_e) // var e

在for循环计数器

  for(let i = 0; i < 3; i++){ // 此处设置循环变量的是for循环计数器的父作用域
      // 此处是for循环计数器的子作用域
      i = 'abc' // 此处覆盖i变量的值,i一旦被改变,循环计数器执行一次后跳出循环
      console.log(i)  // 这里只执行一次打印 abc
  }
  for(let i = 0; i < 3; i++){
      let i = 'abc' // 子作用域再次声明同名的i变量 不会覆盖父作用域的i变量
      console.log(i) // for循环执行三次 打印三次 abc
  } 
  // console.log(i) // 在外面读取i变量会报错: i is no defined

  for(var j = 0; j < 3; j++){
      j = 'efg'  // 覆盖上面的j变量
      console.log(j) // 打印一次
  }
  for(var j = 0; j < 3; j++){
      var j = 'efg'   // 覆盖上面的j变量
      console.log(j) // 打印一次
  }
  var for_a = []
  for(var i = 0; i < 3; i++){
     for_a[i] = function(){
         console.log(i)
     }
  }
  for_a[2]() // 3 
// var 声明的i是全局变量,每次循环i的值都会被更新,for循环结束后 执行for_a[2] 方法打印的i是最新的值
  for(let i = 0; i < 3; i++){
     for_a[i] = function(){
         console.log(i)
     }
  }
  for_a[0]() // 0
  for_a[2]() // 2 i是let声明的变量,每次循环相当于重新创建新的i变量,由于JavaScript引擎会记住上一轮循环的值,因此每次循环的值都会被单独记录下来

不会变量提升

  // 不会变量提升
  console.log(global_f) // undefined  // var 变量会变量提升 即脚本运行时global_f 已经存在了,只是还没被赋值,所以打印undefined
  var global_f = 'var f' 
  console.log(global_g) // 报错:Cannot access 'global_g' before initialization //  不会变量提升,这之前没有声明global_g 也就不存在过,打印就出错
  let global_g = 'let g'

暂时性死区

    var global_h = 'var h'
    {
        // let只要在块级作用域内声明变量,就会与这个作用域绑定
        // global_h = 'var h h'   // 所以在let声明global_h 变量前 对该变量赋值会报错
        // 暂时性死区也意味着 typeof  global_h 也会报错而检查不出变量类型
        typeof x // undefined   x未被声明过
        let global_h = 'let h' // Cannot access 'global_g' before initialization
    }

不允许重复声明

    // 在相同作用域下let不允许重复声明变量,否则报错
    {
        var global_i = 'var i'
        let global_i = 'let i' // 报错:Identifier 'global_i' has already been declared
    }
    {
        let global_j = 'let j'
        let global_j = 'let j1' // 报错:Identifier 'global_j' has already been declared
        {
            let global_j = 'let j2' //不报错,这是一个单独的子作用域
        }
    }
    {
        let global_k = 'let k'
        var global_k = 'var k' // 报错:Identifier 'global_k' has already been declared
    }
为什么需要块级作用域
    es5只存在全局作用域跟函数作用域
    一旦某个全局变量被函数重复声明了,那将导致这个全局变量也被覆盖
 
关于const
    //const跟let一样有块级作用域,同样变量不提升,有暂时性死区, 同一作用域下也是不能再次被声明
//
const声明一个只读的变量,一旦声明,常量的值就不可被改变 const global_l = 'const l' // global_l = 'const l1' // 报错:Identifier 'global_i' has already been declared // const global_l = 'const l2' // 报错:Identifier 'global_l' has already been declared
      // const 一旦声明就必须马上赋值,只声明不赋值就会报错
      const global_m; // Uncaught SyntaxError: Missing initializer in const declaration
 
      tips:const实际上保证的不是变量的值不能被改变,对于基础数据类型(字符串,布尔值,数值)来说,值就保存在变量指向的那个内存地址
           但对于复合类型数据(对象、数组),变量指向的内存地址保存的并不是值,而是一个指向实际数据的指针,const只能保证这个指针不变
           并不能保证实际数据内部的格式是否发生改变
          const global_obj = { a: 'const obj' }
          global_obj.a = 'const obj1' // 不报错

猜你喜欢

转载自www.cnblogs.com/zhangky/p/12213170.html