跳到主要内容

解构赋值

info
  • 解构赋值 是一种特殊的语法,可以将数组、对象、甚至任何可迭代对象“拆包”至一系列变量中。对可迭代对象使用解构赋值,其实是调用 for..of 并进行赋值的操作。

  • 解构赋值不会导致原来的数组或对象或可迭代对象自身被修改。

数组解构

tip

解构数组的完整语法:let [item1 = default, item2, ...rest] = array,这表示数组的第一个元素被赋值给 item1,第二个元素被赋值给 item2,剩下的所有元素被复制到另一个数组 rest

// 以下两种写法是等价的

// let [firstName, surname] = arr;

let firstName = arr[0];
let surname = arr[1];
let [firstName, surname] = "John Smith".split(' ');
alert(firstName); // John
alert(surname); // Smith
  • 可以通过添加额外的逗号来丢弃数组中不想要的元素

  • 解构赋值等号左侧可以是任何“可以被赋值的”东西,比如一个对象的属性。

  • Object.entries(obj) 方法 可以与解构语法一同使用

    let user = {
    name: "John",
    age: 30
    };

    // 使用循环遍历键—值对
    for (let [key, value] of Object.entries(user)) {
    alert(`${key}:${value}`); // name:John, then age:30
    }
  • Map 可以与解构语法一同使用

    let user = new Map();
    user.set("name", "John");
    user.set("age", "30");

    // Map 是以 [key, value] 对的形式进行迭代的,非常便于解构
    for (let [key, value] of user) {
    alert(`${key}:${value}`); // name:John, then age:30
    }
  • 使用解构赋值来交换两个变量的值是一个著名的技巧。

  • 使用三个点 "..." 获取其余项

  • 缺少对应值的变量都会被赋 undefined

  • 解构赋值的变量可以声明默认值,默认值也可以是表达式、函数调用等。不过,这些表达式或函数只会在这个变量未被赋值的时候才会被计算。

    // 默认值
    let [name = "Guest", surname = "Anonymous"] = ["Julius"];

    alert(name); // "Julius"(来自数组的值)
    alert(surname); // "Anonymous"(默认值被使用了)
    // 使用了 prompt 函数来提供两个默认值,注意:prompt 将仅针对缺失值(surname)运行
    let [name = prompt('name?'), surname = prompt('surname?')] = ["Julius"];

    alert(name); // Julius(来自数组)
    alert(surname); // 你输入的值

对象解构

tip

解构对象的完整语法:let {prop : varName = default, ...rest} = object,这表示属性 prop 会被赋值给变量 varName,如果没有这个属性的话,就会使用默认值 default。没有对应映射的对象属性会被复制到 rest 对象。

  • 对象解构赋值可以使用冒号来设置变量名称 { sourceProperty: targetVariable }

  • 解构赋值的变量可以声明默认值,默认值也可以是表达式、函数调用等。不过,这些表达式或函数只会在这个变量未被赋值的时候才会被计算。

    let options = {
    title: "Menu"
    };

    let {width = prompt("width?"), title = prompt("title?")} = options;

    alert(title); // Menu
    alert(width); // (prompt 的返回值)
    // 可以将冒号和等号结合起来
    let options = {
    title: "Menu"
    };

    let {width: w = 100, height: h = 200, title} = options;

    alert(title); // Menu
    alert(w); // 100
    alert(h); // 200
  • 使用三个点 "..." 获取其余项

    实时编辑器
    结果
    Loading...
  • 给已声明的变量解构赋值,需要把整个赋值表达式用括号包起来,否则会报错,报错原因是JavaScript引擎认为花括号是一个代码块。

    let title, width, height;

    {title, width, height} = {title: "Menu", width: 200, height: 100}; // 报错:SyntaxError: Unexpected token '='

嵌套解构

使用冒号设置变量名时进一步解构

智能函数参数

有时,一个函数有很多参数,其中大部分的参数都是可选的。如下:

function showMenu(title = "Untitled", width = 200, height = 100, items = []) {
// ...
}

问题是,在大部分的参数只需采用默认值的情况下,调用这个函数时会需要写大量的 undefined,当我们处理更多参数的时候可读性会变得很差。

// 在采用默认值就可以的位置设置 undefined
showMenu("My Menu", undefined, undefined, ["Item1", "Item2"])

可以用一个对象来传递所有参数,而函数负责把这个对象解构成各个参数:

想全部使用默认值的话,可以传入空对象:

可以通过指定空对象 {} 为整个参数对象的默认值来解决上述的报错: