- 数组的解构赋值
- 对象的解构赋值
- 字符串的解构赋值
- 数值和布尔值的解构赋值
- 函数参数的解构赋值
数组的解构赋值
// 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还没有声明。}
对象的解构赋值
// 对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。 // 对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。 { 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 }
字符串的解构赋值
// 字符串也可以解构赋值// 字符串被转化成了一个类似数组的对象{ 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}
数值和布尔值的解构赋值
// 解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。// 注意:解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。{ let { toString: s } = 123; console.log(s === Number.prototype.toString); // true}{ let { toString: s } = true; console.log(s === Boolean.prototype.toString); // true}
函数参数的解构赋值
// 函数的参数也可以使用解构赋值{ [[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 ]}