1、数组的解构赋值
在以前,我们若是要将数组的每个元素分别赋值给不同变量,较为麻烦。如:
ES6中的解构赋值,允许我们写成这个样子。
let [a, b, c] = [1, 2, 3];
console.log(a, b, c);
上面这段代码表示,可以从数组里面提取值,按照对应的位置,一一给变量赋值。
//左右两边结构得一致 let [a, [[b], c]] = [1, [[2], 3]]; console.log(a, b, c); //1 2 3 let [ , , d] = [1, 2, 3]; console.log(d); //3 let [f, ...g] = [1, 2, 3]; //第一个赋值给f,其他剩余的都装入到数组g中 console.log(f, g); //1 [2,3] let [x, y, ...z] = [1]; console.log(x, y, z); //1 undefined []
解构不成功的时候,变量的值就会是undefined。不完全解构的情况,即等号左边只匹配一部分等号右边的数组,还是可以解构成功的。如下例:
//解构不成功 let [a,b] = []; console.log(a, b); //undefined undefined let [x, y] = [1]; console.log(x, y); //1 undefined //不完全解构 let [c, d] = [1, 2, 3]; console.log(c, d); //1 2
只要某种数据结构具备Iterator接口,都可以采用数组形式的解构赋值。至于什么是Iterator接口,我们下篇再看。
let [a] = 1; //TypeError: 1 is not iterable
等号右边的值是不可遍历的的结构,也就是说不具备Iterator,那么将会报错。set结构和generator函数也可以采用数组形式的解构赋值。
解构赋值允许指定默认值。注意,ES6内部使用 === 来判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。
//默认值 let [a=1, b=2] = ['x']; console.log(a,b); //x 2 let [x, y] = [1, undefined]; console.log(x,y); //1 undefined let [z=1] = [null]; console.log(z); //null (null不严格等于undefined,所以默认值未生效)
2.对象的解构赋值
解构也可以应用于对象,但对象的解构与数组有一个重要的不同点,即,数组的元素是按照次序排列的,变量的取值由其位置决定;对象的属性是没有次序的,变量要与属性名相同,才能取到正确的值。如果解构失败,变量的值为undefined。
let {a, b} = {b:2, a:1}; //顺序不影响,变量名和属性名一致就可以 console.log(a,b); //1 2 let {x} = {a:1, b:2}; //没有对应的同名属性 console.log(x); //undefined
对象的解构赋值,可以将对象的方法赋值到某个变量上。
let {log} = console; //将console对象的log方法赋值给log变量 log('123');
对象的解构赋值的内部机制是,先找到同名的属性,再赋值给对应的变量。
let {a:x, b:y} = {a:1, b:2}; console.log(x, y); //1 2
在上例中,a 和 b 是匹配的模式,x ,y 才是变量,把1 和 2 赋值给 x, y 。
let person = { name: 'lisi', age: 12, friend:{ fname: "zhangsan", fage: 10 } } let {name, friend, friend:{fname}} = person; console.log(name); //lisi console.log(friend); //{ fname: 'zhangsan', fage: 10 } console.log(fname); //zhangsan
如上面代码,嵌套的对象也可以解构。上面代码有三次解构赋值,分别对属性name, friend, fname 进行解构赋值。最后对fname的解构赋值,friend只是模式,变量是fname.
有时,我们会遇到这样的情况,如:animal:{person:{name}},animal 和person 都是模式,变量是 name。只要记住,最后一个冒号后面的就是变量,其他都是模式。
注意,对象的解构赋值可以取到继承的属性。
const obj1 = {}; const obj2 = {a : 123}; Object.setPrototypeOf(obj1, obj2); //将obj2设置为obj1的原型对象 const {a} = obj1; console.log(a); //123
上面代码中,obj1 自身没有 a 属性,而是继承自obj2 的属性。解构赋值可以取到这个属性。
对象的解构也可以指定默认值,与数组类似。
数组本质上是特殊的对象,因此可以对数组进行对象属性的解构。
let arr= [1, 2, 3]; let {0 : a, [arr.length - 1] : b} = arr; console.log(a, b); //1 3
数组arr的第0个位置对应的是1,第[arr.length - 1]位置,也就是第2个位置对应的是3。
3.字符串、数值、布尔值的解构赋值
//字符串的解构赋值 const [a, b, ...c] = 'hello'; //字符串被转换成了一个类似数组的对象 console.log(a); //h console.log(b); //e console.log(c); //[ 'l', 'l', 'o' ] const {length : len} = 'hello'; //字符串被转换成类似于数组的对象,有length属性 console.log(len); //5 //数值和布尔值的解构赋值 //undefined和null无法转为对象,所以对它们进行解构赋值,会报错 //等号右边是数值和布尔值时,会先转为对象,对象里面都有toString属性 let {toString: a} = 123; console.log(a); //[Function: toString] let {toString: b} = true; console.log(a); //[Function: toString]
4.解构赋值的用途
- 交换变量的值
let x = 1; let y = 2; [x, y] = [y, x];
- 从函数返回多个值
//返回一个数组 function show(){ return [1,2,3]; } let [a, b, c] = show(); //返回一个对象 function show(){ return { name: 'lisi', age: 12 }; } let {a, b} = show();
- 函数参数的定义
//参数是一组有次序的值 function f1([x, y, z]) { console.log(x, y, z); } f1([1,2,3]); //1 2 3 //参数是一组无次序的值 function f2({x, y, z}){ console.log(x, y, z); } f2({z:3, y:2, x:1}); //1 2 3
- 提取JSON数据
let json = {a:1, b:"hello", c:[1, 2, 3]}; let {a, b, c} = json; console.log(a, b, c); //1 'hello' [ 1, 2, 3 ]
- 函数参数的默认值
function show({x=0, y=0}){ console.log(x, y); } show({x: 1, y: 2}); //1 2 show({x: 1}); //1 0 show({}); //0 0
- 遍历Map结构
const map = new Map(); map.set('first', 'hello'); map.set('second', 'world'); for(let [key, value] of map){ console.log(key + " is " + value); } //first is hello //second is world
- 输入模块的指定方法