变量的解构赋值[二对象]

  • A+
所属分类:ES 6 JavaScript Web

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

一.对象的解构赋值

1.基本写法

  • 基本写法
    let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
    foo // "aaa"
    bar // "bbb"
    

2.特点

  • ① 对象属性赋值是按照属性名匹配的,和属性顺序无关。
    let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
    foo // "aaa"
    bar // "bbb"
    
  • ② 对象解构无相应属性,赋值为undefined
    let {foo} = {bar: 'baz'};
    foo // undefined
    
  • ③ 对象的解构赋值可以取到继承的属性
    const obj1 = {};
    const obj2 = { foo: 'bar' };
    Object.setPrototypeOf(obj1, obj2);
    
    const { foo } = obj1;
    foo // "bar"
    
  • ④ 与数组一样,解构也可以用于嵌套结构的对象。
    //一.嵌套结构
    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"}]
    //三.关于嵌套解构更多范例:
    //下面代码有三次解构赋值,分别是对loc、start、line三个属性的解构赋值。注意,最后一次对line属性的解构赋值之中,只有line是变量,loc和start都是模式,不是变量。
    const node = {
      loc: {
        start: {
          line: 1,
          column: 5
        }
      }
    };
    
    let { loc, loc: { start }, loc: { start: { line }} } = node;
    line // 1
    loc  // Object {start: Object}
    start // Object {line: 1, column: 5}
    
    //嵌套赋值的例子
    let obj = {};
    let arr = [];
    
    ({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });
    
    obj // {prop:123}
    arr // [true]
    
    // 报错
    //下面代码中,等号左边对象的foo属性,对应一个子对象。该子对象的bar属性,解构时会报错。原因很简单,因为foo这时等于undefined,再取子属性就会报错。
    let {foo: {bar}} = {baz: 'baz'};
    

3.对象解构赋值的本质

  • 对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
    //变量名与属性名处理
    let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
    baz // "aaa"
    
    let obj = { first: 'hello', last: 'world' };
    let { first: f, last: l } = obj;
    f // 'hello'
    l // 'world'
    
    //如下:foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo。
    
    let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
    baz // "aaa"
    foo // error: foo is not defined
    

4.对象解构赋值的使用

  • ① 将现有变量赋值给我们定义的同名变量。
    // 例一   将Math对象的对数、正弦、余弦三个方法,赋值到对应的变量上
    let { log, sin, cos } = Math;
    
    // 例二    console.log赋值到log变量
    const { log } = console;
    log('hello') // hello
    

5.默认值

  • 对象的解构也可以指定默认值。
    var {x = 3} = {};
    x // 3
    
    var {x, y = 5} = {x: 1};
    x // 1
    y // 5
    
    var {x: y = 3} = {};
    y // 3
    
    var {x: y = 3} = {x: 5};
    y // 5
    
    var { message: msg = 'Something went wrong' } = {};
    msg // "Something went wrong"
    
  • 默认值生效的条件是,对象的属性值严格等于undefined。
    var {x = 3} = {x: undefined};
    x // 3
    
    var {x = 3} = {x: null};
    x // null
    

6.解决歧义

  • 如果要将一个已经声明的变量用于解构赋值,可能会出现歧义。
    // 一 错误的写法:因为 JavaScript 引擎会将{x}理解成一个代码块,从而发生语法错误。
    let x;
    {x} = {x: 1};
    // SyntaxError: syntax error
    
    //二 将对象放在一个圆括号里面,解释为对象
    // 正确的写法
    let x;
    ({x} = {x: 1});
    
  • 解构赋值允许等号左边的模式之中,不放置任何变量名。因此,可以写出非常古怪的赋值表达式。
    ({} = [true, false]);
    ({} = 'abc');
    ({} = []);
    
  • 由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。
    let arr = [1, 2, 3];
    let {0 : first, [arr.length - 1] : last} = arr;
    first // 1
    last // 3
    
zhangfeng

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: