Appearance
解构赋值
解构:自动解析数组或对象中的值,并赋值给指定的变量
数组解构
按序次排列,解构不成功 ,返回 undefined
解构空数组,原样返回
js
let [a, b, c] = [1, 2, 3]
let [foo, [[bar], baz]] = [1, [[2], 3]]
let [, , third] = ['foo', 'bar', 'baz']
let [x, y, ...z] = ['a'] // a undefined []
let [a, [b], d] = [1, [2, 3], 4, 5] // 部分解构不能解构不可变量对象
js
// 报错
let [foo] = 1
let [foo] = false
let [foo] = NaN
let [foo] = undefined
let [foo] = null
let [foo] = {}默认值
ES6 内部使用严格相等运算符(===),判断一个位置是否有值,就是判断是否严格等于undefined。
js
let [foo = true] = [] // 指定默认值取默认值为惰性求值
js
let [x = f()] = [1]js
function f() {
console.log('aaa')
}
let [x = f()] = [1] // x能解构到值,不会输出aaa默认值引用其他变量
js
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对象解构
对象解构
解构无次序,但要保证 解构名称与对象名称同名
解构不成功 ,返回 undefined
可以解构原型链上的变量
javascript
// 同名变量可以简写
let { bar, foo } = { foo: 'aaa', bar: 'bbb' }
const { log } = console取别名:真正赋值的变量是别名,而不是原始名称。
js
let { first: f, last: l } = { first: 'hello', last: 'world' }
// first => error: is not undefined
// f => 'hello'解构嵌套对象
js
let obj = {
p: ['Hello', { y: 'World' }]
}
let {
p,
p: [x, { y }]
} = obj
x // "Hello"
y // "World"
p // ["Hello", {y: "World"}]进一步理解解构赋值中的赋值
js
let obj = {}
let arr = []
;({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true })
obj // {prop:123}
arr // [true]默认值
js
var { x = 3 } = {}
x // 3
var { x: y = 3 } = {}
y // 3
var { x: y = 3 } = { x: 5 }
y // 5注意点
- 对声明的变量进行解构
js
// 错误的写法
let x;
{x} = {x: 1}; // SyntaxError: syntax error
// 正确的写法
let x;
({x} = {x: 1});Javascript 会将 {x} 理解为代码块
- 允许等号左边的模式之中,不放置任何变量名。(无意义)
js
;({} = [true, false])
;({} = 'abc')
;({} = [])- 数组本质为特殊对象,可以对数组进行对象解构
js
let arr = [1, 2, 3]
let { 0: first, [arr.length - 1]: last } = arr
first // 1
last // 3字符串解构
js
const [a, b, c, d, e] = 'hello'
let { length: len } = 'hello'字符串会被转为类似数组的对象
数值和布尔值解构
解构赋值时,等号右边的值不是对象或数组,则会先转为对象。
undefined和null无法转为对象,所以解构赋值报错
数值和布尔值的包装对象都有toString属性
js
let { toString: s } = 123
s === Number.prototype.toString // true
let { toString: s } = true
s === Boolean.prototype.toString // true函数参数解构
js
function add([x, y]) {
// ...
}
add([1, 2]) // 3
// 含默认值
function move({ x = 0, y = 0 } = {}) {
return [x, y]
}
move({ x: 3, y: 8 }) // [3, 8]
move({ x: 3 }) // [3, 0]
move({}) // [0, 0]
move() // [0, 0]
function move({ x, y } = { x: 0, y: 0 }) {
return [x, y]
}
move({ x: 3, y: 8 }) // [3, 8]
move({ x: 3 }) // [3, undefined]
move({}) // [undefined, undefined]
move() // [0, 0]函数参数使用解构数组/对象,调用函数不传参数会报错。不能解构 undefined
js
function fn([x, y, z]) {
console.log(x, y, z)
}
fn() //会报错圆括号问题
以下三种情况不使用圆括号
变量声明语句
变量声明语句不能使用圆括号
js
// 全部报错
let [(a)] = [1];
let {x: (c)} = {};
let ({x: c}) = {};
let {(x: c)} = {};
let {(x): c} = {};
let { o: ({ p: p }) } = { o: { p: 2 } };函数参数
函数参数也属于变量声明
js
// 报错
function f([(z)]) { return z; }
// 报错
function f([z,(x)]) { return x; }赋值语句
js
// 全部报错
({ p: a }) = { p: 42 };
([a]) = [5];
[({ p: a }), { x: c }] = [{}, {}];可以使用圆括号
赋值语句,并且圆括号不属于模式(解构)一部分。
js
;[b] = [3] // 正确
;({ p: d } = {}) // 正确
;[parseInt.prop] = [3] // 正确第一行语句中,模式是取数组的第一个成员,跟圆括号无关; 第二行语句中,模式是p,而不是d; 第三行语句与第一行语句的性质一致。
应用
(1)交换变量的值
js
;[x, y] = [y, x](2)从函数返回多个值 (3)函数参数的定义 (4)提取 JSON 数据 (5)函数参数的默认值 (6)遍历 Map 结构
js
const map = new Map()
map.set('first', 'hello')
map.set('second', 'world')
for (let [key, value] of map) {
console.log(key + ' is ' + value)
}js
// 获取键名
for (let [key] of map) {
// ...
}
// 获取键值
for (let [, value] of map) {
// ...
}(7)输入模块的指定方法
js
const { SourceMapConsumer, SourceNode } = require('source-map')