按照必定的模式从数组或者对象中取值,对变量进行赋值的过程称为「解构」数组
在 ES5 中,为变量赋值只能直接指定值:spa
var a=1,b=2,c=3 a; // 1 b; // 2 c; // 3
可是在 ES6 中,咱们能够被容许写成:code
var [a,b,c]=[1,2,3]; a; // 1 b; // 2 c; // 3
ES6 中能够很明显看出来,咱们能够在数组中取数据,按照位置的对应关系对变量赋值。对象
解构赋值容许使用默认值
var [foo = true] = []; foo; // true
[x,y = 'b'] = ['a'] x; // "a" y; // "b"
[x,y = 'b'] = ['a','c'] x; // "a" y; // "c"
ES6 内部使用的是严格相等运算符(===)判断一个位置是否有值。因此,若是一个数组成员不严格等于 undefind,默认值是不会生效的。rem
var [x = 1] = [undefined]; x; // 1
null == undefined // true var [x = 1] = [null]; x; // null
上述代码中,一个数组成员是 null,所以默认值不生效。由于 null 不严格等于 undefined。it
function f(){ console,log('aaa'); } let [x = f()] = [1]; // undefined ,不执行 f() x; // 1
var {foo,bar}={foo:"aaa",bar:"bbb"}; foo; // "aaa" bar; // "bbb"
对象的解构赋值和数组有一个不一样,数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。io
var {laf} = {foo:"aaa",bar:"bbb"}; laf; // undefined;
在上面代码中,变量没有对应的同名属性,致使取不到值,最后等于 undefind。
实际上,对象的解构赋值是如下形式的简写。console
var { foo: foo, bar: bar } = { foo:"aaa", bar:"bbb" }
实际上,在对象的解构赋值的内部机制,是先找到同名属性,而后在赋值给对应的变量。真正被赋值的是后者,而不是前者。function
var { foo : bar } = {foo : "aaaa"}; foo; // foo is not defined bar; // "aaaa"
采用这种写法是,变量的声明和赋值都是一体的。对于 let 和 const 而言,变量不能从新声明,因此一旦赋值的变量之前声明过,就会报错。class
let foo; let {foo}={foo:'1'} // Uncaught SyntaxError: Identifier 'foo' has already been declared
因此不能重复 let 声明:
let foo; ({foo} = {foo:1})
对象的解构也能够制定默认值。
var {x,y = 5} = {x:1}; x; // 1 y; // 5
默认值生效条件是,对象属性严格不等于 undefined
var {x = 3} = {x: undefined}; x; // 3 var {x = 3} = {x:null}; x; // null
和数组同样,解构也能够用于嵌套解构的对象。
var obj={ p:[ "hello", {y:"world"} ] }
这时的 p 是模式,不是变量,所以不会被赋值。若是 p 也要做为变量赋值,应该写成这样:
var obj = { p:{ "Hello", { y:"World" } } } let {p, p : { x , [ { y } ] = obj; x // "Hello" y // "World" p // ["Hello", {y: "World"}]
下面一个例子:
var {loc,loc:{start},loc:{ start: { { line,column } } }={ loc:{ start:{ line:1, column:5 } } }
上面代码有三次解构赋值,分别是对loc、start、line三个属性的解构赋值。注意,最后一次对line属性的解构赋值之中,只有line是变量,loc和start都是模式,不是变量。
var obj = []; var arr = []; ({foo:obj.prop,bar: arr[0]} = {foo:123,bar:true}); obj; // {prop:123} arr; // [true]
若是解构模式是嵌套的对象,并且子对象所在的父属性不存在,则会报错
var {foo : {bar}} = {baz:'baz'};
正确的写法:
var {foo,foo:{bar}}={foo:{bar:'bar'}};