Skip to content
  • 数组的解构赋值
  • 对象的解构赋值
  • 字符串的解构赋值
  • 数值和布尔值的解构赋值
  • 函数参数的解构赋值

数组的解构赋值

javascript
// ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)
{
  // es5
  let a = 1
  let b = 2
  let c = 3
  console.log(a, b, c) // 1 2 3
}
{
  // es6
  let [a, b, c] = [1, 2, 3]
  console.log(a, b, c) // 1 2 3
}
// 可以从数组中提取值,按照对应位置,对变量赋值。
// 本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值
{
  let [a, [[b], c]] = [1, [[2], 3]]
  console.log(a, b, c) // 1 2 3
}
{
  let [, , c] = [1, 2, 3]
  console.log(c) // 3
}
{
  let [a, , c] = [1, 2, 3]
  console.log(a, c) // 1 3
}
{
  let [a, b, ...rest] = [1, 2, 3, 4, 5, 6]
  console.log(a, b, rest) // 1 2 [3, 4, 5, 6]
}
{
  // 如果解构不成功,变量的值就等于undefined
  let [a, b, ...c] = ['Di-got']
  console.log(a, b, c) // Di-got undefined []

  // 另一种情况是不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功。
  let [d, e] = [1, 2, 3]
  console.log(d, e) // 1 2

  let [f, [g], h] = [1, [2, 3], 4]
  console.log(f, g, h) // 1 2 4
}
{
  // 默认值
  let [x = 1, y = x] = [] // x=1; y=1
  let [x = 1, y = x] = [2] // x=2; y=2
  let [x = 1, y = x] = [1, 2] // x=1; y=2
  let [x = y, y = 1] = [] // ReferenceError: y is not defined
  // x用y做默认值时,y还没有声明。
}

对象的解构赋值

javascript
    // 对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

    // 对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
    {
        let { a, b } = { a: 1, b: 2 };
        console.log(a, b);    // 1 2
    }
    {
        // 变量没有对应的同名属性,导致取不到值,最后等于undefined(解构失败,变量的值等于undefined。)
        let { a } = { b: 2 };
        console.log(a); // undefined
    }
    {
        // 默认值
        let { x = 3 } = {};
        console.log(x); // 3

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

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

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

        let { message: msg = 'Something went wrong' } = {};
        console.log(msg); // "Something went wrong"
    }
    {
        // 已经声明的变量用于解构赋值
        // 错误写法
        let x;
        {x} = {x: 1}; // SyntaxError: syntax error
        // JavaScript 引擎会将{x}理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。

        // 正确的写法 (将整个解构赋值语句,放在一个圆括号里面,就可以正确执行)
        let x;
        ({x} = {x: 1});

        // 由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。
        let arr = [1, 2, 3];
        let { 0: first, [arr.length - 1]: last } = arr;
        console.log(first, last); // 1 3
    }
    {
        let metaData = {
            title: 'wcd',
            test: [{
                title: 'test',
                desc: 'description'
            }]
        }
        let { title: esTitle, test: [{ title: cnTitle }] } = metaData;
        console.log(esTitle, cnTitle);    // wcd test
    }

字符串的解构赋值

javascript
// 字符串也可以解构赋值
// 字符串被转化成了一个类似数组的对象
{
  const [a, b, c, d, e] = 'hello'
  console.log(a, b, c, d, e) // h e l l o
}
{
  // 类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。
  let { length: len } = 'hello'
  console.log(len) // 5
}

数值和布尔值的解构赋值

javascript
// 解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。
// 注意:解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。
{
  let { toString: s } = 123
  console.log(s === Number.prototype.toString) // true
}
{
  let { toString: s } = true
  console.log(s === Boolean.prototype.toString) // true
}

函数参数的解构赋值

javascript
// 函数的参数也可以使用解构赋值
{
  ;[
    [1, 2],
    [3, 4],
  ].map(([a, b]) => a + b) // [3, 7]
}
// 函数参数的解构也可以使用默认值
// 函数moveOne的参数是一个对象,通过对这个对象进行解构,得到变量x和y的值。如果解构失败,x和y等于默认值。
{
  function moveOne({ x = 0, y = 0 } = {}) {
    return [x, y]
  }

  moveOne({ x: 3, y: 8 }) // [3, 8]
  moveOne({ x: 3 }) // [3, 0]
  moveOne({}) // [0, 0]
  moveOne() // [0, 0]
}
// 函数move的参数指定默认值,而不是为变量x和y指定默认值,所以会得到与前一种写法不同的结果。
{
  function moveTwo({ x, y } = { x: 0, y: 0 }) {
    return [x, y]
  }

  moveTwo({ x: 3, y: 8 }) // [3, 8]
  moveTwo({ x: 3 }) // [3, undefined]
  moveTwo({}) // [undefined, undefined]
  moveTwo() // [0, 0]
}
// undefined就会触发函数参数的默认值。
{
  ;[1, undefined, 3].map((x = 'yes') => x) // [ 1, 'yes', 3 ]
}