ES6学习笔记之解构赋值

1、数组的解构赋值

在以前,我们若是要将数组的每个元素分别赋值给不同变量,较为麻烦。如:

let arr = [1, 2, 3];
let a = arr[0];
let b = arr[1];
let c = arr[2];

ES6中的解构赋值,允许我们写成这个样子。

let [a, b, c] = [1, 2, 3];
console.log(a, b, c);

上面这段代码表示,可以从数组里面提取值,按照对应的位置,一一给变量赋值。

//左右两边结构得一致
let [a, [[b], c]] = [1, [[2], 3]];  
console.log(a, b, c);   //1 2 3

let [ , , d] = [1, 2, 3];
console.log(d);   //3

let [f, ...g] = [1, 2, 3];  //第一个赋值给f,其他剩余的都装入到数组g中
console.log(f, g);  //1 [2,3]

let [x, y, ...z] = [1];
console.log(x, y, z); //1 undefined []

解构不成功的时候,变量的值就会是undefined。不完全解构的情况,即等号左边只匹配一部分等号右边的数组,还是可以解构成功的。如下例:

//解构不成功
let [a,b] = [];
console.log(a, b);  //undefined undefined
let [x, y] = [1];
console.log(x, y);  //1 undefined
//不完全解构
let [c, d] = [1, 2, 3];
console.log(c, d);  //1 2

只要某种数据结构具备Iterator接口,都可以采用数组形式的解构赋值。至于什么是Iterator接口,我们下篇再看。

let [a] = 1;    //TypeError: 1 is not iterable

等号右边的值是不可遍历的的结构,也就是说不具备Iterator,那么将会报错。set结构和generator函数也可以采用数组形式的解构赋值。

 解构赋值允许指定默认值。注意,ES6内部使用 === 来判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。

//默认值
let [a=1, b=2] = ['x'];
console.log(a,b);   //x 2

let [x, y] = [1, undefined];
console.log(x,y);  //1 undefined

let [z=1] = [null];
console.log(z); //null (null不严格等于undefined,所以默认值未生效)

2.对象的解构赋值

解构也可以应用于对象,但对象的解构与数组有一个重要的不同点,即,数组的元素是按照次序排列的,变量的取值由其位置决定;对象的属性是没有次序的,变量要与属性名相同,才能取到正确的值。如果解构失败,变量的值为undefined。

let {a, b} = {b:2, a:1};    //顺序不影响,变量名和属性名一致就可以
console.log(a,b);   //1 2
let {x} = {a:1, b:2};   //没有对应的同名属性
console.log(x); //undefined

对象的解构赋值,可以将对象的方法赋值到某个变量上。

let {log} = console;    //将console对象的log方法赋值给log变量
log('123');

对象的解构赋值的内部机制是,先找到同名的属性,再赋值给对应的变量。

let {a:x, b:y} = {a:1, b:2};
console.log(x, y);  //1 2

在上例中,a 和 b 是匹配的模式,x ,y 才是变量,把1 和 2 赋值给 x, y 。

let person = {
    name: 'lisi',
    age: 12,
    friend:{
        fname: "zhangsan",
        fage: 10
    }
}
let {name, friend, friend:{fname}} = person;    
console.log(name);  //lisi
console.log(friend);    //{ fname: 'zhangsan', fage: 10 }
console.log(fname); //zhangsan

如上面代码,嵌套的对象也可以解构。上面代码有三次解构赋值,分别对属性name, friend, fname 进行解构赋值。最后对fname的解构赋值,friend只是模式,变量是fname.

有时,我们会遇到这样的情况,如:animal:{person:{name}},animal 和person 都是模式,变量是 name。只要记住,最后一个冒号后面的就是变量,其他都是模式。

注意,对象的解构赋值可以取到继承的属性。

const obj1 = {};
const obj2 = {a : 123};
Object.setPrototypeOf(obj1, obj2);  //将obj2设置为obj1的原型对象

const {a} = obj1;
console.log(a); //123

上面代码中,obj1 自身没有 a 属性,而是继承自obj2 的属性。解构赋值可以取到这个属性。

对象的解构也可以指定默认值,与数组类似。

数组本质上是特殊的对象,因此可以对数组进行对象属性的解构。

let arr= [1, 2, 3];
let {0 : a, [arr.length - 1] : b} = arr;
console.log(a, b);  //1 3

数组arr的第0个位置对应的是1,第[arr.length - 1]位置,也就是第2个位置对应的是3。

3.字符串、数值、布尔值的解构赋值

//字符串的解构赋值
const [a, b, ...c] = 'hello';   //字符串被转换成了一个类似数组的对象
console.log(a); //h
console.log(b); //e
console.log(c); //[ 'l', 'l', 'o' ]
const {length : len} = 'hello'; //字符串被转换成类似于数组的对象,有length属性
console.log(len);   //5

//数值和布尔值的解构赋值
//undefined和null无法转为对象,所以对它们进行解构赋值,会报错
//等号右边是数值和布尔值时,会先转为对象,对象里面都有toString属性
let {toString: a} = 123;    
console.log(a); //[Function: toString]
let {toString: b} = true;
console.log(a); //[Function: toString]

4.解构赋值的用途

  1. 交换变量的值
    let x = 1;
    let y = 2;
    [x, y] = [y, x];
  2. 从函数返回多个值
    //返回一个数组
    function show(){
        return [1,2,3];
    }
    let [a, b, c] = show();
    //返回一个对象
    function show(){
        return {
            name: 'lisi',
            age: 12
        };
    }
    let {a, b} = show();
  3. 函数参数的定义
    //参数是一组有次序的值
    function f1([x, y, z]) {
        console.log(x, y, z);
    }
    f1([1,2,3]);    //1 2 3
    //参数是一组无次序的值
    function f2({x, y, z}){
        console.log(x, y, z);
    }
    f2({z:3, y:2, x:1});    //1 2 3
  4. 提取JSON数据
    let json = {a:1, b:"hello", c:[1, 2, 3]};
    let {a, b, c} = json;
    console.log(a, b, c);   //1 'hello' [ 1, 2, 3 ]
  5. 函数参数的默认值
    function show({x=0, y=0}){
        console.log(x, y);
    }
    show({x: 1, y: 2}); //1 2
    show({x: 1});   //1 0
    show({});   //0 0
  6. 遍历Map结构
    const map = new Map();
    map.set('first', 'hello');
    map.set('second', 'world');
    for(let [key, value] of map){
        console.log(key + " is " + value);
    }
    //first is hello
    //second is world
  7. 输入模块的指定方法

 

 

 

posted @ 2019-06-04 18:42  糖小圆  阅读(284)  评论(0编辑  收藏  举报