ES6声明变量的六种方式:

ES5只有两种声明变量的方法: var命令和function命令.ES6除了letconst命令,另外还有importclass声明方式.ES6一共有6种声明变量的方法. (还有var定义的变量存在变量提升)

CONST命令定义常量相关

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

const声明的变量不得改变,这就意味着,const一旦声明变量,就必须立即初始化,不能留到后面赋值.

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动.对于简单类型的数据(数值,字符串,布尔值),值就保存在变量指向的那个内存地址.因此等同于常量.但是对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了.

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

顶层对象的属性相关:

顶层对象,在浏览器环境指的是window对象,在Node指的是global对象.在ES5之中,顶层对象的属性与全局变量是等价的.

ES6为了改变这一点,一方面规定,为了保证兼容性,var命令和function命令声明的全局变量,依旧是顶层对象属性.另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。

数组和对象的结构赋值

1.数组的解构赋值:

本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。

    let [a,b,c] = [1,2,3];
    
    let [foo, [[bar], baz]] = [1, [[2], 3]];
    foo // 1
    bar // 2
    baz // 3

2.对象的解构赋值:

解构不仅可以用于数组,还可以用于对象.

    let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
    foo // "aaa"
    bar // "bbb"

对象的解构与数组有一个重要的不同.数组的元素是按照次序排列的,变量的取值由他的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值.

    let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
    foo // "aaa"
    bar // "bbb"
    
    let { baz } = { foo: 'aaa', bar: 'bbb' };
    baz // undefined

上面代码的第一个例子,等号左边的两个变量的次序,与等号右边两个同名属性的次序不一致,但是对取值完全没有影响。第二个例子的变量没有对应的同名属性,导致取不到值,最后等于undefined

有时候在工作中会遇到多层解构赋值,例如如下代码:


async getIconcate() {
      let res = await api.getIndexIcon({ terminal: 0 });
      const {
        //resultContent: { resultContent },
        resultContent: { resultContent:resData },
        resultFlag,
        resultMsg
      } = res.data;

      if (resultFlag) {
        this.insuranceTypes = resData;
        //this.insuranceTypes = resultContent.slice(0,5);
      } else {
        toToast(resultMsg);
      }
        // console.log('resData',resData);
        //return resultContent
      return resData;
}

多层解构赋值

使用babel转换后的代码如下:

babel转换后

与数组一样,解构也可以用于嵌套解构的对象.

    let obj = {
      p: [
        'Hello',
        { y: 'World' }
      ]
    };
    
    let { p: [x, { y }] } = obj;
    x // "Hello"
    y // "World"

注意,这时p是模式,不是变量,因此不会被赋值.如果p也要作为变量赋值,可以写成下面这样.

    let obj = {
      p: [
        'Hello',
        { y: 'World' }
      ]
    };
    
    let { p, p: [x, { y }] } = obj;
    x // "Hello"
    y // "World"
    p // ["Hello", {y: "World"}]

下面是另外一个例子.

    
const node = {
       loc:{
       start:{
        line:1,
        column:5
       } 
    }
}

let { loc, loc: { start }, loc: { start: { line,column }} } = node;
console.log(line,column); //1   5
line  //1
loc   //Object {start:Object}
start //Object {line:1,column:5}

函数参数的解构赋值

    function add([x,y]){
        return x+y;
    }
    add([1,2]); //3

在上面的代码中,函数add的参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量xy,对于函数内部的代码来说,他们能感受到的参数就是xy

解构赋值的一些用途

(1).交换变量的值:

    let x = 1;
    let y = 2;
    
    [x, y] = [y, x];

(2).从函数返回多个值:

函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回.有了解构赋值,取出这些值就非常方便.

    
    // 返回一个数组
    function example() {
      return [1, 2, 3];
    }
    let [a, b, c] = example();
    
    // 返回一个对象
    function example() {
      return {
        foo: 1,
        bar: 2
      };
    }
    let { foo, bar } = example();

(3).函数参数的定义

解构赋值可以方便的将一组参数与变量名对应起来.

    // 参数是一组有次序的值
    function f([x, y, z]) { ... }
    f([1, 2, 3]);
    
    // 参数是一组无次序的值
    function f({x, y, z}) { ... }
    f({z: 3, y: 2, x: 1});

(4).解构赋值对提取JSON对象中的数据,尤其有用.(接口联调中经常这么用)

    let jsonData = {
      id: 42,
      status: "OK",
      data: [867, 5309]
    };
    
    let { id, status, data: number } = jsonData;
    
    console.log(id, status, number);
    // 42, "OK", [867, 5309]

(5).函数参数的默认值

    jQuery.ajax = function (url, {
      async = true,
      beforeSend = function () {},
      cache = true,
      complete = function () {},
      crossDomain = false,
      global = true,
      // ... more config
    } = {}) {
      // ... do stuff
    };

指定参数的默认值,就避免了在函数体内部在写var foo = config || 'default foo';这样的语句.