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也不能用用于解构!
解构的一些用途
- 交换变量
let a = 1;
let b = 2;
[a,b] = [b,a];
- 函数传参中的解构
// 参数是一组有次序的值
function foo1([width,height,left,right]) {
console.log(width,height,left,right)
}
foo1([100, 200, 300, 300])
// 参数是一组无次序的值
function foo2({width,height,left,right}){
console.log(width,height,left,right)
}
foo2({left:300, width:100, right:300, height:200})
- 将函数返回的结果直接解构
// 返回一个数组
function foo() {
return [1, 2, 3];
}
let [a, b, c] = foo();
// 返回一个对象
function foo2() {
return {
a: 1,
b: 2
};
}
let { a, b } = foo2();
- 引入模块的指定方法
加载模块时,往往需要指定输入那些方法
import { xxx} from 'xxxx'
xxx();
可以看到解构在工作中还是非常好用的!
有个注意点:
关于括号的用法
如果在解构之前就已经定义了变量,大括号{}位于行首时,JS引擎 就会认为 {name} 是一个代码块,所以等号就出问题了。
let name;
{name}={name:'Alice'};//报错
解决方式是在包裹一层括号()
let name;
({name}={name:'Alice'});
小括号的出现,让整个解构赋值的结构被看做一个代码块,这样内部的 {name} 模式则可以正常匹配到
以上就是解构相关的全部内容!
网友评论