对象的解构赋值

解构不仅可以用于数组,还可以用于对象,直接来看个简单粗暴的

    let { first, second } = { first: 1, second: 2 };
    console.log(first, second); //1 2

与数组解构不同的是,数组的元素是按次序排列的,变量取值是由它的位置(下标)决定。在对象的属性中没有次序,变量与属性同名,才能取到正确的值

    //等号左边两个变量的次序跟右边不一致,对取值完全没影响
    let { second, first } = { first: 1, second: 2 };
    console.log(first, second); //1 2

    //等号左边的变量没有对应的同名属性,所以取不到值,遂等于undefined
    let { thrid } = { first: 1, second: 2 };
    console.log(thrid); // undefined

如果变量名与属性名不一样,需要写成下面这样

    let { foo: first } = { foo: 'AAA', bar: 'BBB' };
    console.log(first); // AAA

    let obj = { first: 'AAA', second: 'BBB' };
    let { first: a, second: b } = obj;
    console.log(a, b); // AAA BBB
    
    //上两例说明,对象的解构赋值其实就是下面形式的简写
    let { first: first, second: second } = { first: 1, second: 2 };
    console.log(first, second); //1 2

对象的解构赋值机制是先找到同名属性,再赋值给对应的变量。真正被赋值的是后者,而不是前者

    //first是匹配的模式,second才是变量,被赋值的是变量second,
    let { first: second } = { first: 'FIRST', second: 'SECOND' };
    console.log(first); //报错:first is not defined
    console.log(second); // FIRST

解构也可以用于嵌套解构的对象

    let obj = {
        first: [
            'AAA',
            {
                second: 'BBB'
            }
        ]
    }
    let { first: [a, { second }] } = obj;
    //此时,first为匹配模式,相当于[a, { second }] = ['AAA',{second: 'BBB'}]
    //先是数组的解构赋值,然后是对象的解构赋值
    console.log(a, second);// AAA BBB

此时,first是模式,不是变量,不会被赋值,如果first也要作为变量赋值的话,可以写成这样

    let obj = {
        first: [
            'AAA',
            {
                second: 'BBB'
            }
        ]
    }
    let { first, first: [a, { second }] } = obj;
    //相当于 let { first: first, first: [a, { second }] } = obj;
    console.log(a, second); // AAA BBB
    console.log(first); // ["AAA", {second: "BBB"}]

再举个

    const obj = {
        loc: {
            start: {
                line: 1,
                column: 2
            }
        }
    }
    let { loc, loc: { start }, loc: { start: { line } } } = obj;
    //相当于这样:let { loc: loc, loc: { start: start }, loc: { start: { line: line } } } = obj;
    //分别有三次解构赋值,分别是对loc,start,line三个属性的解构赋值
    //在最后一次对line属性解构赋值中,只有line是变量,loc和start都是模式
    console.log(loc); // {start: {line: 1, column: 2}}
    console.log(start); // {line: 1, column: 2}
    console.log(line); // 1

再来个嵌套赋值的

    let obj = {};
    let arr = [];
    ({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true })
    //此时,foo和bar是匹配模式,被赋值的是 obj和 arr
    console.log(obj); // {prop: 123}
    console.log(arr); // [true]

为什么上面的代码中({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true })用括号包起来,是因为JavaScript引擎会将 { foo: obj.prop, bar: arr[0] }理解为一个代码块,从而发生语法错误。

  • 错误写法

      let x; 
      { x } = { x: 1 }; //报错
    
  • 正确写法

      let x;
      ({ x } = { x: 1 });
      console.log(x); // 1
    

对象的解构也可以指定默认值

    let { a = 3 } = {};
    console.log(a); // 3

    let { b, c = 3 } = { b: 1 };
    console.log(b); // 1
    console.log(c); // 3

    let { x: y = 3 } = {};
    console.log(y); // 3

    let { j: i = 3 } = { j: 1 };
    console.log(i); // 1

    let { message: msg = 'Hello Mr Wang' } = {};
    console.log(msg); // Hello Mr Wang

默认值的生效条件是:对象的属性值严格等于undefined

    let { x = 1 } = { x: undefined };
    console.log(x); // 1

    let { x = 1 } = { x: null };
    //相当于这样:let { x: x = 1 } = { x: null };
    console.log(x); // null

解构失败的话,变量值等于undefined

    let { x } = { y: 1 }
    console.log(x); // undefined

如果解构模式是嵌套的对象,子对象所对应的父属性不存在会报错

    let { x: { y } } = { y: y }
    console.log(y); //报错

对象的解构赋值,可以很方便的将现有对象的方法,赋值到某个变量

     //将Math对象的其中三个方法,赋值到对应变量上,使用起来会很方便
    let { abs, max, min } = Math;
    console.log(abs(-10)); //10
    console.log(max(1, 2)); //2
    console.log(min(1, 2)); //1

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

    let arr = [1, 2, 3];
    let { 0: first, [arr.length - 1]: last } = arr;
    //数组arr的下标(键)0 ,对应值是 1
    //[arr.length-1]就是数组arr的下标 2,对应的值是 3 
    console.log(first); // 1
    console.log(last); // 3

你可能感兴趣的:(对象的解构赋值)