3、常用的解构赋值


常用的解构赋值

1、字符串

// 1、字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。
{
    const [a, b, c, d, e] = 'hello';
    console.log(a);   // "h"
    console.log(b);   // "e"
    console.log(c);   // "l"
    console.log(d);   // "l"
    console.log(e);   // "o"
}

// 2、类似数组的对象都有一个length属性,因此还可以拥有length属性的对象进行解构赋值。
{
    let { length } = 'hello';
    console.log('length: ', length);
}

2、对象的解构赋值可以取到继承的属性

{
    // 1.解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。
    let { toString: s } = 123;
    console.log(' s: ',  s); // ƒ toString() { [native code] }
    console.log(s === Number.prototype.toString);   // true

    /* 这里的s为什么变成了函数toString()了呢?这是因为123如果转为对象,可能是这样:
     {123: '123'}
        123: "123"
        [[Prototype]]: Object
        constructor: ƒ Object()
        hasOwnProperty: ƒ hasOwnProperty()
        isPrototypeOf: ƒ isPrototypeOf()
        propertyIsEnumerable: ƒ propertyIsEnumerable()
        toLocaleString: ƒ toLocaleString()
        toString: ƒ toString()
        valueOf: ƒ valueOf()
    这里的123转对象的规则是什么,转成什么样子其实我也不太清楚,这里是我假象的,但是不管怎么转,顶层都会有toString方法。
	原型链上有toString()方法,而对象的解构赋值可以取到继承的属性,自然s就是toString方法了。*/  
}

{
    // 2. 解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。
    // 由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。
    let { prop: x } = undefined;    // TypeError
    let { prop: y } = null;         // TypeError
    // Cannot destructure property 'prop' of 'undefined' as it is undefined.
}

3、交换变量的值

{
    let x = 1;
    let y = 2;
    [x, y] = [y, x];
    console.log(x, y);//2 1
    //上面代码交换变量x和y的值,这样的写法不仅简洁,而且易读,语义非常清晰。
}

4、从函数取出多个值

{
    // 函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。
    function example() {
        return {
            foo: "val1",
            bar: "val2"
        };
    }
    let { foo, bar } = example();
    console.log(foo, bar);//val1 val2
}

5、函数参数的定义(*)

{
    // 解构赋值可以方便地将一组参数与变量名对应起来。
    // 1.参数是一组有次序的值
    function f([x, y, z]) {
        console.log('z: ', z);
        console.log('y: ', y);
        console.log('x: ', x);
    }
    console.log(f([1, 2, 3])); // z:  3 y:  2 x:  1


    // 2.参数是一组无次序的值 解构赋值可以方便地将一组参数与变量名对应起来。
    function f({ x, y, z }) {
        return [x, y, z]
    }
    console.log(f({ z: 3, y: 2, x: 1 }));   //(3) [1, 2, 3]返回数组形式
    //返回的形式完全可以由需求决定,数组、对象都可以。
}

6、函数参数的解构也可以使用默认值。(*)

{
    function move({ x = 0, y = 0 } = {}) {
        return [x + y]
    }
    console.log(move({ x: 1, y: 2 }));   //  3   
    console.log(move({ x: 999 }));       //  999  
    // 做一个分析:
    // 这里{ x: 999 }为实参,传入后,{ x = 0, y = 0 }就要与{ x: 999 }进行模式匹配,发现y找不到对应模式,故y=undefined,此时y解构失败,就会启用默认值y = 0;记住解构失败,启用默认值就好。

    console.log(move({}));               //  0 
    console.log(move());                 //  0
    console.log("-----------------------");
    // 上面代码中,函数move的参数是一个对象,通过对这个对象进行解构,得到变量x和y的值。如果解构失败,x和y等于默认值。
}

7、为函数move的参数指定默认值(*)

{
    function move({ x, y } = { x: 0, y: 0 }) {
        return [x, y]
    } 
    // 下面代码是为函数move的参数指定默认值,而不是为变量x和y指定默认值,所以会得到与前一种写法不同的结果。
    // 刚开始我一下子也没看明白这是怎么回事,但是突然想起来函数传参时的形参与实参关系。
    move({ x: 1, y: 2 })  //>>>>>  [1, 2] 
    // 这里move的x\y都能匹配到对应的模式,既{ x: 1, y: 2 },所以正常输出

    move({ x: 999 })  //>>>>>  [999, undefined]  
    // 这里模式x能正常匹配,但是y没有传入,y取值时找不到,所以为undefined

    move({})  //>>>>>  [undefined, undefined]
    // 这里x\y都找不到对应匹配的模式,所以都为undefined

    move()  //>>>>>  [0, 0]
    // 这里相当于没有传入模式,此时才会使用参数解构的默认值,既{ x: 0, y: 0 }

    // 那么,move({ q: 1, y: 2 })会返回什么呢?
    // 根据对象的解构匹配模式的定义,很明显,只有y能正常匹配模式,找不到模式x,自然x就为undefined,所以输出为:[undefined, 2]
}

8、解构赋值对提取 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]
    // 上面代码可以快速提取 JSON 数据的值。
}

9、ES6…扩展操作符骚操作

// 复制和合并数组变得更为简洁。不需要使用 concat() 方法或 slice() 方法,一个 ...操作符已经足够:
{
    const arr1 = [10, 20, 30];
    const copy = [...arr1];
    console.log(copy);    // → [10, 20, 30]   

    const arr2 = [40, 50];
    const merge = [...arr1, ...arr2];
    console.log(merge);    // → [10, 20, 30, 40, 50]
}

10、将数组作为一个需要单独一个个传入参数的函数的参数

{
    const arr = [10, 20, 30]
    // equivalent to  console.log(Math.max(10, 20, 30));
    console.log(Math.max(...arr));    // → 30
}

11、 对象属性展开复制(*)

{
    const obj1 = {
        a: 10,
        b: 20
    };
    const obj2 = {
        ...obj1,
        c: 30
    };
    console.log(obj2);    // → {a: 10, b: 20, c: 30}
    
    // 如果存在相同的值 后者覆盖前者
    {
        const obj2 = {
            ...obj1,
            a: 30
        };
        console.log(obj2);    // → {a: 30, b: 20}
    }   
}

12、合并对象 类似于object.assign(*)

{
    const obj1 = { a: 10 };
    const obj2 = { b: 20 };
    const obj3 = { c: 30 };

    // ES2018
    console.log({ ...obj1, ...obj2, ...obj3 });    
    // → {a: 10, b: 20, c: 30}

    // ES2015
    console.log(Object.assign({}, obj1, obj2, obj3));    
    // → {a: 10, b: 20, c: 30}   
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值