ES6的解构赋值

1,597 阅读4分钟

今天我们来聊聊解构赋值

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;

可以看到这是非常高效的。

解构的过程相当于就是分解、匹配的过程。解构赋值的过程就是按照一定的模式从数组或对象中取值,再赋值给对应变量的过程。

那我们先来看数组的解构

数组的解构赋值

  1. 一维数组的解构

根据数组数据的下标,有次序的赋值;

let [a,b,c] = [1,2,3];//es6
console.log(a); // 1
console.log(b); // 2
console.log(c);  // 3
  1. 对嵌套多维数组的解构
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
  1. 不需要匹配的位置可以置空
let [,,c] = [1, 2, 3];
console.log(c);//3
  1. 使用...扩展运算符,匹配余下的所以值,形成一个数组
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]
  1. 左边数组中没有找到右边数组中对应值,其值为undefined
let [x,y,z] = [1,2];
console.log(x); // 1
console.log(y); // 2
console.log(z);  // undefined

以上几种情况可以证实,本质上只要等号两边模式一致,左边变量即可获取右边对应位置的值。这真的是太方便了。

除了数组的解构,对象也能解构

对象的解构赋值

  1. 特点

数组的解构是按次序排列的,变量的取值由它的位置决定;而对象的解构必须是变量名与属性名一致,才能取到正确的值

let { a, b } = { a : 1, c : 2 };
console.log(a);//1
console.log(b);//undefined
  1. 对任意深度的嵌套对象进行解构
let obj= {
   arr: [1,{ a: 2 } ]
 };
 let { arr: [x, { y}] } = obj;
 console.log(x); // 1
 console.log(y); // 2
  1. 可自定义属性名称(取别名)

上面说到,对象的解构变量名必须要属性名一致才能取到对应的值,有的时候我不想用对象里面的值作为变量,那我又得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也不能用用于解构!