概述
1.解构赋值是对赋值运算符的扩展。
优点:在代码书写上简洁且易读,语义更加清晰明了;也方便了复杂对象中数据字段获取。
2.是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。
解构赋值核心是声明标识符(变量)按照某种数据模型(js中只有数组和对象)解析(即取出数据模型的成员值)并赋值给声明的标识符(变量)。数组形式解构赋值 需要按照对应位置。对象的解构赋值是与变量名有关,变量标识符必须与对象成员同名,才能取到正确的值。
数组和对象的数据模型:数组中括号[],对象大括号{}。
数组和对象取成员的用法(解析):数组取元素中括号[]加下标,对象取成员点语法。
解构模型
在解构中,解构的源就是传入的对象和数组,解构赋值表达式的右边部分。解构的目标就是被赋值的变量,解构赋值表达式的左边部分。
报错的原因:解析错误,obj3.x1取出的是undefined,undefined和null是基本数据无法包装对象不能保存数据也不能调点语法取成员。解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于 undefined 和 null 无法转为对象,所以对它们进行解构赋值,都会报错。解构赋值时,如果等号右边是数值和布尔值,则会先包装对象。
解构的目标(标识符)在数组中相当于占位符,这个标识符用于保存解构源的数组中对应下标的数据,而对象中的标识符就是对象的成员名,解构源的对象中有这个成员且成员名和解构目标的标识符一样。如果对象的成员名和标识符不一致,则是undefined,表示该标识符取出对象不存在的成员会取对象原型链上的成员,原型链上也没有就会取出undefined。
解构默认值
解构赋值不成功的变量的值等于undefined,即不完全解构。
let [a, b] = [1]; // a = 1, b = undefined
//隐式操作:let a=[][0] let b=[][1]
let obj = { p: [{ y: 'world' }] };
let { p: [{ y }, x] } = obj; // x = undefined y = 'world'
//隐式操作:let p=obj.p let y=p[0].y let x=p[1]
console.log(a,b,666);
console.log(x,y,777);
当不想从解构源中解构出的值为undefined,解构赋值允许指定默认值。
let arr=[{age:20},{name1:"karen"}]
let [{age,name1="jack"}]=arr
//隐式操作:let name1=jack name1=arr[0].name1
//先将默认值赋值给该变量标识符,再取出对应的解构源中的数据赋值给变量标识符
let [a = 6, b=7] = [];
console.log(age,name1);
console.log(a,b);
默认值不一定为字面量,也可以引用解构赋值的其他变量,但该变量必须已声明。
let [x = 1, y = x] = []; // x=1; y=1
let sample30 = 31;
let { sample31 = sample30, sample32 = 3 } = {};
console.log(x,y,666);
console.log(sample31, sample32,777); // 31, 3
ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个解构源中的成员严格等于undefined,默认值才会生效。即使该解构源中有成员保存了undefined作为值也会让默认值生效但null不会让默认值生效。
let arr=[{age:26,name1:"jzx"},{name1:"gem"}]
let [{age,name1="phm"}]=arr
let [a = 6, b=7] = [null,undefined];
console.log(age,name1,777);
console.log(a,b,666);
函数参数也可以解构赋值
字符串的解构赋值
字符串也可以解构赋值。当字符串进行解构赋值的时候,字符串被转换成了一个类数组。类数组也有length属性,所以可以通过这个方式获取字符串的长度。
let str = "jzxphmgem";
let { length } = str;
let [a, b, c, d, e] = 'hello';
console.log(length,666);//9
console.log(a, b, c, d, e,777); //h e l l o
对数组进行对象属性的解构
由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。
let { 0: sample0, 1: sample1 } = [1, 2];
//隐式操作:let simple0=arr[0] let simple1=arr[1]
console.log(sample0, sample1);
解构赋值的使用场景
不用临时变量,交换两个变量的值
let a=6;
let b=7;
[b,a]=[a,b]
console.log(a,b);
函数多个返回值的解构赋值
function useState(num){
function fn(arg){
//让外界的count变量改变为arg
};
return [num,fn];
};
var [count,setCount]=useState(0);//说明该函数需要返回一个数组作为解析源
//隐式操作var count=[][0]; var setCount=[][1];
console.log(count);//0
setCount(2000);
console.log(count);//2000
提取JSON数据
可以使用解构赋值一次性提取多个数据
let jsonData = {
id: 7,
status: false,
data: [{ name: 'jzx' }, { name: 'phm' }, { name: 'gem' }]
};
let { id, status, data } = jsonData;
console.log(id, status, data);
// 7, false, [{ name: 'jzx' }, { name: 'phm' },{ name: 'gem' }]
解构赋值声明变量的注意点
//解构声明变量是声明解构的最小单位
let obj={name:"jzx",age:26,music:{music_name:["an"]}};
let {name,music:{music_name}}=obj;
console.log(name);
console.log(music_name);
console.log(music);
解构时声明的变量是声明解构的最小单位,所以是声明的music_name