变量的解构赋值 - 对象篇

2020-10-20  本文已影响0人  坏丶毛病

上次讲了数组的解构赋值,这次来看下对象的解构赋值

对象的解构和数组不同之处在于,数组的元素是按次序排列的,变量的取值是由位置决定的,而对象的属性没有次序,变量必须与属性同名才能取到正确的值

 let { bar, foo } = { foo: 'aaa', bar: 'bbb'};
 console.log(foo, bar);    // aaa, bbb

 let { baz } = { foo: 'aaa', bar: 'bbb' };
 console.log(baz);       // undefined

好了,话不多说,来看一些demo吧

  // 如果变量名与属性名不一致,必须写成下面这样
  let { a: c } = { a: 'aaa', b: 'bbb'};
  console.log(c);     // aaa

  let obj = { first: 'hello', last: 'world'};
  let { first: f, last: l } = obj;
  console.log(f, l);    // hello, world

  // 实际上说明,对象的解构赋值是下面形式的简写
  // let { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb'};

  // 也就是说,对象的解构赋值的内部机制是先找到同名属性,然后再赋值给对应的变量,真正被赋值的是后者,而不是前者
  // 下面的例子说明:d是匹配的模式,e才是变量,真正被赋值的是变量e,而不是模式d
  let { d: e } = { d: 'aaa', bar: 'bbb'}
  console.log(e);     // aaa
  // console.log(d);     // d is not defined

  // 与数组一样,解构也可以用于嵌套的对象
  let obj2 = {
    p: [
      'Hello',
      { y: 'World'}
    ]
  };

  let { p: [x, { y }] } = obj2;
  console.log(x, y);    // Hello, World
  // 这里p只是作为匹配模式,不是变量,如果p也要作为变量赋值,可以写成如下这样
  let { p, p: [g, { h }] } = obj2;
  console.log(g, h);    // Hello, World
  console.log(p);       // ['Hello', { y: 'World'}]

  // 以下代码有三次解构赋值,分别是对loc、start、line三个属性的解构赋值,需要注意,最后一次对line属性的解构赋值中,只有line是变量,loc和start都是模式
  var node = {
    loc: {
      start: {
        line: 1,
        column: 5
      }
    }
  };
  var { loc, loc: { start }, loc: { start: { line }} } = node;
  console.log(loc);     // {start: { line: 1, column: 5 } }     对象Object
  console.log(start);   //  { line: 1, column: 5 }      对象Object
  console.log(line);    // 1

  // 嵌套赋值的例子:
  let obj3 = {};
  let arr = [];
  ({ foo: obj3.prop, bar: arr[0] } = { foo: 123, bar: true})
  console.log(obj3);    // { prop: 123}
  console.log(arr);     // [true]

  // 对象的解构赋值也可以指定默认值
  var { i = 3 } = {};
  console.log(i);     // 3

  var { j, k = 5 } = { j: 1 };
  console.log(j, k);    // 1, 5

  var { m: n = 3 } = {}
  console.log(n);     // 3

  var { o: q = 3 } = { o: 5 };
  console.log(q);     // 5

  var { message: msg = 'Something went wrong' } = {};
  console.log(msg);     // 'Something went wrong'

  // 默认值生效的条件是:对象的属性值严格等于undefined(===)
  var { r = 3 } = { r: undefined };
  console.log(r);       // 3

  var { s = 3 } = { s: null };
  console.log(s);       // null:不严格等于undefined,所以默认值不会生效

  // 如果解构失败,变量的值等于undefined
  let { name } = { age: 18 };
  console.log(name);    // undefined

  // 如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么会报错
  let { foo: { sex }} = { baz: 'baz'};    // 报错:foo在对象中取不到,此时等于undefined,再取子属性就会报错
  // 上述代码类似于下面这样:
  let _temp = { baz: 'baz' };
  console.log(_tmp.foo.sex);

  // 如果要将一个已经声明的变量进行解构赋值,必须注意
  /*
    错误的写法:(报错)
      let x;
      { x } = { x: 1 };

    正确的写法:(加个括号,只有不将大括号放在行首,从而避免js将其解释为代码块)
    let x;
    ({ x } = { x: 1});
  */

  // 解构赋值允许等号左边的模式之中不放置任何变量名,因此可以写成很多古怪的赋值表达式,虽然有些毫无意义,但是语法都是合法的,可以正常执行
  ({} = [true, false]);
  ({} = 'abc');
  ({} = []);

  // 对象的解构赋值可以很方便的将现有对象的方法赋值到某个变量
  // 例如:将Math对象的对数、正弦、余弦三个方法赋值到对应变量
  let { log, sin, cos } = Math;

  // 由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构赋值
  let arr2 = [1, 2, 3];
  let { 0: one, [arr2.length - 1]: two} = arr2;
  console.log(one);     // 1
  console.log(two);     // 3

以上,就是对象的解构赋值。

数组解构赋值:数组的解构赋值

变量的解构赋值 - 字符串、数值、布尔值、函数参数:变量的解构赋值 - 字符串、数值、布尔值、函数参数

如有问题,请指出,接受批评。

上一篇 下一篇

猜你喜欢

热点阅读