解构赋值
解构赋值是对赋值运算符的扩展。
他是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。
在代码书写上简洁且易读,语义更加清晰明了;也方便了复杂对象中数据字段获取。
解构模型
在解构中,有下面两部分参与:
解构的源,解构赋值表达式的右边部分。
解构的目标,解构赋值表达式的左边部分。
解构失败,变量多
let [a,[b,c],[d,[e,f,[g]]]]=[1,[2,3],[,[,6,[7]]]]
console.log(a,b,c,d,e,f,g);//1 2 3 undefined undefined 6 7
不完全解构,值多了
let [a,[b,c],[,[e,f,[g]]]]=[1,[2,3],[4,[5,6,[7]]]]
console.log(a,b,c,d,e,f,g);//Uncaught ReferenceError: d is not defined
默认值
let [a1 = 6] = []; //6
let [a2 = 6] = [undefined]; //6
let [a3 = 6] = [null]; //null
let [a4, b4 = 2] = [1]; //1 2
let [a5 = 6] = [false]; //false
let [a8 = 6] = ['']; //''
function test1(){
console.log(10);
return 1;
}
let [a6 = test1()] = []; //undefined
console.log(a6);//1
function test2(){
console.log(10);//10
return 99;
}
let [a7 = test2()] = [undefined]; //1
console.log(a7);//99
let [x=1,y=x];
console.log(x,y);//Uncaught SyntaxError: Missing initializer in destructuring declaration(未捕获的SyntaxError:在析构声明中缺少初始化器)
let [x=1,y=x]=[2];
console.log(x,y);//2 2
let [x=y,y=1]=[];
console.log(x,y);//Uncaught ReferenceError: Cannot access 'y' before initialization
对象的解构
学习前认识一下以下的方法。
var name = '王五';
var age = 12;
var person = {
name,
age,
sex: 'male',
eat() {
console.log();
}
}
//属性拼接
let firstName = 'wang';
let secondName = 'wu';
let name = 'wang wu';
let person = {
[firstName + secondName]: name;
}
进入正题
let {a: a, b: b, c: c} = {a: 1, b: 2, c: 3 };
console.log(a, b, c);
let {a,b,c} = {a: 1, b: 2, c: 3 };
console.log(a, b, c);
需要注意点:
这样子是报错的,JS引擎认为大括号不是一个对象了,是个语法块。提示语法不通过:Uncaught SyntaxError: Unexpected token ‘=’。
let a;
{a}={a:1};
console.log(a);//Uncaught SyntaxError: Unexpected token '='
但是可以通过括号的方式,让其变成表达示的方式使其成立:
let a;
({a}={a:1});
console.log(a);
用let/var 声明,加()就报错:Uncaught SyntaxError: Invalid destructuring assignment target
var [(a)]=[1];
var ({a:b})={};
var {(a):b}={};
var {a:(b)}={};
不用let/var 声明:
[(a)]=[1];
//({b:b1})={b:1};//报错
//{(c):c1}={c:1};//报错
//{d:(d1)}={d:1};//报错
//{(e:e1)}={e:1};//报错
console.log(a);//3
//============================
var a={};
[(a.b)]=[3];
console.log(a.b);//3
数组到对象之前的匹配,数组也是特殊的对象,也能进行结构赋值:
let arr = [1, 2, 3];
var {
0: first,
[arr.length - 1]: last
} = arr;
console.log(first, last);//1 3
括号/表达示,返回的是一个值或引用指向,而不是一个变量
变量的值交换:
let a=10,b=20;
[b,a]=[a,b];
模式的匹配可以匹配同源属性(同一个源属性)
let {a:x,b:y}={a:1};
console.log(x,y);
练习一下:
var x = 200,
y = 300,
z = 100;
var obj = {x: {y: 42},z: {y: z}};
({y: x = {y: y}} = obj);//x = {y: y}是给x设置一个默认值,所以x的默认值是: x={y:300}
({z: y = {y: z}} = obj);//y = {y: z}是给y设置一个默认值,所以x的默认值是: y={y:100}
({x: z = {y: x}} = obj);//z = {y: x}是给z设置一个默认值,所以x的默认值是: y={y:100},但是x在obj中是可以找到的,所以弃用。使用默认值,x={y:42},直接负值给z,就是x={y:42}
console.log(x.y, y.y, z.y);
函数默认值
ES5声明默认值的方式
falsy(虚值) //在通过boolean转换过后,认定为假的值,就叫虚值
function foo(x, y) {
//x=x||1;
//y=y||2;
//console.log(x+y);
//上面的方式不合适,应该使用下面的这种
var a = typeof(arguments[0]) !== 'undefined' ? arguments[0] : 1;
var b = typeof(arguments[1]) !== 'undefined' ? arguments[1] : 2;
console.log(a + b);
}
foo();
foo(5, 6);
foo(null, 6);;
foo(0, 5);
//falsy(虚值) //在通过boolean转换过后,认定为假的值,就叫虚值
ES6声明函数值的方式:
function foo(x=1, y=2) {
}
foo();
/
let x = 1;
function foo(x = x) {
//let x=2;
console.log(x);//Uncaught ReferenceError: Cannot access 'x' before initialization
}
foo();
//
let x = 1;
function foo(x = x) {
//let x=2;
console.log(x);//Uncaught ReferenceError: Cannot access 'x' before initialization
}
foo();
///
var w = 1,
y = 6,
z = 7;
function foo(x = w + 1, y = x + 1, z = z + 1) {
console.log(x, y, z);//Uncaught ReferenceError: Cannot access 'z' before initialization
}
foo();
惰性求值,每一次都需要重新计算表达式的值。