数组的解构赋值
针对数组,在解构赋值时,使用的是模式匹配,只要等号两边数组的模式相同,右边数组的值就会相应赋给左边数组的变量。通俗讲就是基于数组元素的索引,只要左右两侧的数组元素索引相同就可以。
let [arg1, arg2] = [12, 34];console.log(num1); // 12console.log(num2); // 34// 可以使用逗号作为占位符,只解构需要的值let [, , num3] = [12, 34, 56];console.log(num3); // 56// 右边数组的值不足以将左边数组的值全部赋值时,会解构失败,对应的值就等于“undefined”。let [num1, num2, num3] = [12, 34];console.log(num2); // 34console.log(num3); // undefined
(1)数组解构默认值
在数组解构时设置默认值,可以防止出现解构得到undefined值的情况
let [num1 = 1, num2] = [, 34];console.log(num1); // 1console.log(num2); // 34
ES6在判断解构是否会得到undefined值时,使用的是严格等于(===)。只有在严格等于undefined的情况下,才会判断该值解构为undefined,默认值生效的条件是解构值严格等于undefined。
let [num1 = 1,num2 = 2,num3 = 3,num4 = 4] = [null, '', undefined]; //console.log(num1); // null 因为null并不严格等于undefined,默认值不会生效。console.log(num2); // '' 空字符串,也不是undefined,默认值也不会生效。console.log(num3); // 3 值为undefined,默认值生效console.log(num4); // 4 并没有对应的值,因此会解构为undefined,默认值生效
(2)互换值
数组解构也可以用来进行值的互换,而不需要创建临时变量
// 以前写法var a = 1;var b = 2;var tmp; // 临时变量tmp = a;a = b;b = tmp;console.log(a); // 2console.log(b); // 1// 数组解构赋值var a = 1;var b = 2;// 使用数组的解构赋值交换变量[b, a] = [a, b];console.log(a); // 2console.log(b); // 1
(3)嵌套数组的解构
let [num1, num2, [num3]] = [12, [34, 56], [78, 89]];console.log(num1); // 12console.log(num2); // [34, 56]console.log(num3); // 78
(4)函数参数解构
当函数的参数为数组类型时,可以将实参和形参进行解构
function foo([arg1, arg2]) {console.log(arg1); // 2console.log(arg2); // 3}foo([2, 3]);
(5) 解析函数返回的数组
函数返回数组,使用数组的解构赋值,可以快速地获取数组元素值。
function fn() {return [12, 34];}let [num1, num2] = fn();console.log(num1); // 12console.log(num2); // 34
对象的解构赋值
对象中的属性是没有顺序的,这就要求右侧解构对象的属性名和左侧定义对象的变量名必须相同,这样才可以进行解构。同样,未匹配到的变量名在解构时会赋值“undefined”。
let {m, n, o} = {m: 'kingx', n: 12};console.log(m); // kingxconsole.log(n); // 12console.log(o); // undefined
事实上,对象解构赋值的原理是:先找到左右两侧相同的属性名(key),然后再赋给对应的变量(value),真正被赋值的是value部分,key并不会被赋值。
let {m: m, n: n} = {m: 'kingx', n: 12};// 简写方案let {m, n} = {m: 'kingx', n: 12};let {m: name, n: age} = {m: 'kingx', n: 12};console.log(name); // kingxconsole.log(age); // 12
(1)对象解构的默认值
对象解构时同样可以设置默认值,默认值生效的条件是对应的属性值严格等于undefined。
let {m, n = 1, a: age = 2, o = true} = {m: 'kingx', o: null};console.log(m); // kingxconsole.log(n); // 1 当属性名和变量名不相同时,用默认值。console.log(age); // 2 当属性名和变量名不相同时,用默认值。console.log(o); // null,因为null与undefined不严格相等,默认值并未生效
(2)嵌套对象的解构
嵌套的对象同样可以进行解构,解构时从最外层对象向内部逐层进行,每一层对象值都遵循相同的解构规则。
let obj = {p: ['Hello',{y: 'World'}]};let {p: [x, {y: name}]} = obj;console.log(x); // Helloconsole.log(name); // Worldconsole.log(y); // ReferenceError: y is not defined
注意:当父层对象对应的属性不存在,而解构子层对象时,会出错并抛出异常。
let obj = {m: {n: 'kingx'}};let {o: {n}} = obj;console.log(n); // TypeError: Cannot read properties of undefined (reading 'n')
(3)选择性解构对象的属性
假如一个对象有很多通用的函数,那么可以使用解构赋值来获取其中的几个函数。
let { min, max } = Math;console.log(min(1, 3)); // 1console.log(max(1, 3)); // 3
(4)函数参数解构
当函数的参数是一个复杂的对象类型时,我们可以通过解构去获得想要获取的值并赋给变量。
function who({displayName: Name, fullName: {firstName: name}}){console.log(Name + "is" + name);}const user = {id: 42,displayName: "jdoe",fullName: {firstName: "John",lastName: "Doe"}};who(user); // jdoe is John
