ECMAScript(解构)

解构

数组解构

  • 基本用法
    let [a , b] = [1, 2] // a = 1 b = 2
    let [a, b] = 1 // 报错
    let [a, b] = [1] // a = 1 b = undefined
    let [a, b] = [1, null] // a = 1 b = null
    let [a, ...b] = [1, 2, 3, 4] // a = 1 b = [2, 3, 4]
    let [x, y, z] = new Set(['a', 'b', 'c']) // x = a  y = b  z = c
    
  • 默认值
    let [x = 1, y = x] = [2];    // x=2; y=2
    

对象解构

  • 基本用法
    let { bar, foo } = { foo: 'aaa', bar: 'bbb' }; // bar = bbb foo = aaa
    let { bar, foo } = { bar: 'bbb' }; // bar = bbb foo = undefined
    // let {bar, foo} 是 let {bar: bar, foo: foo} 的简写 真正赋给值的是:后的
    // 例如
    let { bar: foo } = { bar: 'bbb', foo: 'aaa'} // foo = bbb
    
    // 下面代码中,foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo
    let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
    baz // "aaa"
    foo // error: foo is not defined
    
  • 用于嵌套结构的对象
    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"}]
    
    如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错。
    // 报错
    let {foo: {bar}} = {baz: 'baz'};
    
  • 对象的解构赋值可以取到继承的属性
      const obj1 = {};
      const obj2 = { foo: 'bar' };
      Object.setPrototypeOf(obj1, obj2);
    
      const { foo } = obj1;
      foo // "bar"
    
    上面代码中,对象obj1的原型对象是obj2。foo属性不是obj1自身的属性,而是继承自obj2的属性,解构赋值可以取到这个属性。
  • 默认值
 let {x, y = 5} = {x: 1};
 x // 1
 y // 5

 let {x: y = 3} = {};
 y // 3

 let {x: y = 3} = {x: 5};
 y // 5

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

let {x = 3} = {x: undefined};
x // 3

let {x = 3} = {x: null};
x // null
  • 注意点
    如果要将一个已经声明的变量用于解构赋值

    // 错误的写法
    let x;
    {x} = {x: 1};
    // SyntaxError: syntax error\
    // 因为 JavaScript 引擎会将{x}理解成一个代码块,等号左边是不允许出现代码块语句的,从而发生语法错误
    
    // 正确的写法
    let x;
    ({x} = {x: 1});
    

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

    let arr = [1, 2, 3];
    let {0 : first, [arr.length - 1] : last} = arr;
    first // 1
    last // 3
    

字符串的解构

const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"


let {length : len} = 'hello';
len // 5

数值和布尔值的解构赋值

解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。

let {toString: s} = 123;
s === Number.prototype.toString // true

let {toString: s} = true;
s === Boolean.prototype.toString // true



let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError

数值和布尔值的包装对象都有toString属性,因此变量s都能取到值。
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。

函数参数赋值解构

[[1, 2], [3, 4]].map(([a, b]) => a + b);

赋值默认值同上

圆括号问题

不可使用圆括号

  • 声明语句(函数参数也是声明)
let ([a]) = [1] 或(let [a] = [1]) // 报错
  • 括号包含了模式
({a: b}) = {a: 1}
{(a): b} = {a: 1}

使用圆括号

{a: (b)} = {a: 1}
({a: b} = {a: 1})
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。