今天我们来聊聊解构赋值
ES6的解构赋值本质上是属于一种“模式匹配”、“映射关系”;只要等号两边的模式相同,一一对应,左边的变量就会被赋予右边对应的值。其作用可以让代码变得更简洁、可读性变得更高
var arr =[1,2,3,4,5,6,7,8,9];
//没有解构赋值前
var a= arr[0];
var b= arr[1];
var c= arr[2];
var d= arr[3];
var e= arr[4];
var f= arr[5];
var g= arr[6];
var h= arr[7];
var i = arr[8];
//使用解构赋值
let[a,b,c,d,e,f,g,h,i] = arr;
可以看到这是非常高效的。
解构的过程相当于就是分解、匹配的过程。解构赋值的过程就是按照一定的模式从数组或对象中取值,再赋值给对应变量的过程。
那我们先来看数组的解构
数组的解构赋值
- 一维数组的解构
根据数组数据的下标,有次序的赋值;
let [a,b,c] = [1,2,3];//es6
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
- 对嵌套多维数组的解构
let [a, [[b], c],d] = [1, [[2], 3],4];
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
console.log(d); // 4
- 不需要匹配的位置可以置空
let [,,c] = [1, 2, 3];
console.log(c);//3
- 使用...扩展运算符,匹配余下的所以值,形成一个数组
let[a,b,...c] = [1,2,3,4,5,6,7,8,9];
console.log(a); // 1
console.log(b); // 2
console.log(c); //[3,4,5,6,7,8,9]
- 左边数组中没有找到右边数组中对应值,其值为undefined
let [x,y,z] = [1,2];
console.log(x); // 1
console.log(y); // 2
console.log(z); // undefined
以上几种情况可以证实,本质上只要等号两边模式一致,左边变量即可获取右边对应位置的值。这真的是太方便了。
除了数组的解构,对象也能解构
对象的解构赋值
- 特点
数组的解构是按次序排列的,变量的取值由它的位置决定;而对象的解构必须是变量名与属性名一致,才能取到正确的值
let { a, b } = { a : 1, c : 2 };
console.log(a);//1
console.log(b);//undefined
- 对任意深度的嵌套对象进行解构
let obj= {
arr: [1,{ a: 2 } ]
};
let { arr: [x, { y}] } = obj;
console.log(x); // 1
console.log(y); // 2
- 可自定义属性名称(取别名)
上面说到,对象的解构变量名必须要属性名一致才能取到对应的值,有的时候我不想用对象里面的值作为变量,那我又得let一个变量赋值过去吗?其实不用!ES6也想到这样的问题,所以可以在解构的变量名后面自定义属性名称如:
var {name, id: ID} = { name: 'jack', id: 1 };
console.log(ID)// 1
console.log(id) // Uncaught ReferenceError: id is not defined
说白了其内部机制,是先找到同名属性,然后再赋给对应的变量;真正被赋值的是后者。
可以利用解构对象的特点,简写经常用于代码
let {log} = console;
log("hello word"); //console.log === log
除了可以解构对象和数组,对于其他类型能解构吗?
一起来试试
先来看字符串
let [a,b,...c] = "alice";
console.log(a,b,c);//打印出a l ["i", "c", "e"]
神奇,字符串也能当数组一样解构出来。
要注意的是,不能以为是经过了包装类,而将字符串作为对象来解构。那是找不到值的。
let {a} = "alice";
console.log(a);//undefined
想想也是,包装类身上也跟本没有这个a属性
但是如果想要字符串包装类上的属性和方法,那是可以的
let {length,indexOf:index,slice} = "alice"
console.log(length);//5
console.log(index);//indexOf() { [native code] }
console.log(slice);//slice() { [native code] }
小结:字符串也能使用解构赋值,如果解构字符串的字符,可以类似像数组那样解构,如果要使用String.prototype的属性可以像解构对象那样,根据变量名去找属性名所对应的值。
看完字符串的解构赋值,其实我们大概能猜到,其实number类型的数字以及boolean的true和false也应该可以解构,至少可以像解构对象那样,解构其包装类上对应的方法,到底能不能呢?
先来测试number数值型的解构赋值吧
发现1
let [a,...b] = 1234;
console.log(a,b);//Uncaught TypeError: 1234 is not iterable
发现2
let {toFixed:toF} = 1234;
console.log(toF(2));//TypeError
原来数字类型不能像字符串像对象那样解构,也不能像字符串像数组那样解构,提示 not iterable,不是可迭代对象
布尔值也是一样的提示
let [a,...b] = true;//Uncaught TypeError: true is not iterable
let [x,...y] = false;//Uncaught TypeError: false is not iterable
也就是说,只要是不能迭代的东西就不能用于解构,一解构就会报错。因此null、undefined也不能用用于解构!