【es6】 let & const

let


对变量的声明

特性

  • let 只在命令所在代码块有效
  • 不存在变量提升
  • 区块中存在let const 会形成封闭作用域(在定义此之前使用typeof 会抛出 //ReferenceError)
  • 相同作用域不可重复声明(函数内部不可重新声明参数)

1.let 只在命令所在代码块有效

    {
        let a = 10
    }
    a //a is not defined

for循环计数适合使用let命令,仅作用域有效,普通var声明会全局有效
2. let 不存在变量提升

    typeof a //"undefined"

    typeof b //ReferenceError: b is not defined(报错)
    let b = 1   

3.区块中存在let const 会形成封闭作用域(在变量声明前使用会报错,即“暂时性死区”)

    var o = 1
    {
        o = 2 //ReferenceError: o is not defined
        let o
    }
    function bar(x=y, y=2){}
    bar() //ReferenceError: y is not defined(x=y,此时y还没有声明,属于“死区”)

4.相同作用域不可重复声明(函数内部不可重新声明参数)

    function(a) {
        let a //报错
        var b
        let b //报错
        {
            let a //不报错
        }
    }

块级作用域

在es6之前存在两种作用域类型:

  • 全局作用域
  • 块级作用域
    由var声明的变量都存在变量提升
    es6使用let和const体现块级作用域,不存在变量提升,但在es6中var依旧存在变量提升

1.es5的问题

    var tmp = new Data()
    function f() {
      console.log(tmp);
      if (false) {
        var tmp = "hello world";  //变量提升,内层tmp变量覆盖外层tmp变量
      }
    }
    f(); // undefined

2.es6的块级作用域

  • 外层作用域无法读取内层作用域的变量
  • 内层作用域可以定义外层作用域的同名变量
  • 块级作用域外部无法调用块级作用域内部定义的函数

针对函数

  1. es5中规定函数可在顶层作用域,函数作用域中声明,不可在块级作用域中声明,但声明了浏览器也支持
  2. es6可在块级作用域中声明,声明行为相当于let,外部不可访问,但浏览器有的不遵循~
'use strict';
    if (true) {
      function h() {return 0}
    }
    h() //Uncaught ReferenceError: h is not defined

es6的浏览器遵循如下规则

  • 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
  • 函数声明还会提升到所在的块级作用域的头部
所以
    if (true) {
      function h() {return 0}
    }
    h() //0 非严格模式下,不报错
但是
    if (false) {
        function f() { console.log('I am inside!'); }
    }
    f(); //f is not a function
因为相当于var变量提升后是这样的
    var f = undefined;
    if (false) {
        function f() { console.log('I am inside!'); }
    }
    f(); //f is not a function
  1. let 实际为js新增了代码块级作用域,块级作用域中可声明函数(仅在大括号中有用)但在块级作用域之外不可使用 (要避免,必须时写成函数表达式)
  2. 严格模式下,函数只能在顶层作用域或者函数内声明,其他情况(比如if代码块,循环代码块)下声明会报错

const


特性

  • const声明只读常量,修改会报错,只声明不赋值也会报错
  • 不提升,同上存在暂时性死区,声明后才可用
  • 不可重复声明常量
  • 声明常量保存的是地址(即不能改变常量的指向,但可以改变其指向地址里的内容)
    const foo = {}
    foo.prop = 123
    foo.prop //123

const foo = Object.freeze( { } ) 可将对象冻结, 不可添加新属性。

    const foo = Object.freeze({})
    foo.prop = 123 //添加新属性不起作用

但是上述方法,没有冻结对象里的所有属性,冻结对象里的所有属性:

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

跨模块常量

export 输出
import 引用

全局对象属性

  1. 浏览器全局对象是 window对象 ,全局对象的属性 == 全局变量
    a = 2
    window.a //2
  1. var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。
  2. 不是全局对象的属性返回undefined

其他

  1. do 关于使得块级作用域可以变为表达式,可以返回值
  2. 引入global作为顶层对象

你可能感兴趣的:(es6,javascript)