ES6解构赋值原理详解

2022-07-20 10:19:12

ES6解构赋值

ES6变量的解构赋值本质上是“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予匹配的右边的值,如果匹配不成功变量的值就等于undefined

数组的解构赋值

ES6中只要某种数据有Iterator接口(也就是可以循环迭代),都可以进行数组的解构赋值。
Example1:数组的解构

var [a,b,c] = [1,2,3];
var [d,[e],...f] = [4,[5],6,7,8];
console.log(a); //结果为1,b,c结果是2,3
console.log(e,f) //e结果为5,f的结果是一个数组:[6,7,8]

Example2:Set解构赋值

let [x,y] = new Set([1,2]);
console.log(x,y);   //结果为1和2

Example3:Generator函数解构赋值

function* fun(){
    let a = 0;
    let b = 1;
    while(true){
        yield a;
        [a,b] = [b,a+b];
    }
}
let [first,second,third,fourth,fifth,sixth] = fun();
console.log(sixth); //结果为5

Example4:默认值

var [a=3,b=5] = [undefined,4];
console.log(a,b); //结果为3和4

代码解读:上面的代码等同于如下:
Example4:

var a;
var b;
var c = [undefined,4];  //这步骤是另加上去作为数组引用的
if(c[0] !== undefined){
    a = c[0];
}else{
    a = 3;
}
if(c[1] !== undefined){
    b = c[1];
}else{
    b = 5;
}
console.log(a,b);   //结果为3,4

对象的解构赋值

数组的解构是按次序排列的,变量取值由位置决定的,而对象的属性是没有顺序的,变量必须与属性同名才能取到正确的值。

Example

var {b,a} = {a:3,b:4}
console.log(a,b);   //结果为3,4

代码解读:上面的代码等同下面的代码
Example

var _ab = {a:3,b:4};
var b = _ab.b;
var a = _ab.a;
console.log(a,b);   //结果为3,4

注意:对象的解构相当于先定义了后一个对象变量为_ab,再对前一个对象解构出来的变量按照对象先后顺序分别进行申明并使用对象_ab去按照该变量名赋值相应的值。如果前一个对象中的变量和后一个对象中的属性不一致,直接定义是肯定赋值失败的,解决方法如下:
Example

var {b:c,a:d} = {a:3,b:4};
console.log(b,c,a,d)    // 分别是undefined,4,undefined,3

代码解读:上面代码等同下面的代码

Example

var _ab = {a:3,b:4};
var c = _ab.b;
var d = _ab.a;
console.log(b,c,a,d)    // 分别是undefined,4,undefined,3

注意:例子可以看出对象的解构的内部机制是先找到同名属性,然后再赋予相应的变量,真正被赋予的是前一个对象后一个变量,即c,d;而不是前一个对象前一个模式,即b,a;

发现:如果想要上一个例子的模式不为undefined,那么代码可以写成如下:

var e = {b:c,a:d} = {a:3,b:4};
console.log(e.b,b,c,e.a,a,d)    // 分别是4,undefined,4,3,undefined,3

注意:以上代码在使用babel转换的时候可能会出错,只在浏览器中有用,所以最好不要代码中使用,只理解就好

对象解构赋值与数组解构赋值在申明的时候的一点区别:

Example1:数组

let a;
[a] = [3]
console.log(a); //结果为3

Example2:对象

let a;
{a} = {a:3}
console.log(a); // 报错:SyntaxError

代码解读:JavaScript引擎会将[a]理解成一个数组,而将{a}理解成什么呢?对于{a}这个代码在JS中可能会存在两种解释,一种是它是一个表达式,表示含有a属性的一个对象;第二种它是一个语句(代码块),为了消除这种歧义,js开发人员规定只要行首是大括号的,一律解析成代码块。解决上诉问题的代码如下:
Example3:对象

let a;
({a} = {a:3})   //JS中括号中的都是表达式
console.log(a); // 结果3

解构赋值中的圆括号问题

Example

let [(a)] = [1];
let {(b):c} = {b:2};
let {d:(e)} = {d:2};    //都报错:SyntaxError

注意:以上出现错误的原因都是:1、它们都是申明语句;2、圆括号中的都属于模式中的一部分。要同时不满足以上两个条件是比较困难的,所以,ES6规定,只要可能导致解构歧义就不得使用圆括号。所以,建议在写的过程中除了上面的那个对象圆括号的例子可以使用外,其他的情况都不能使用。

ES6中还存在字符串、数组、布尔值等各种解构赋值,基本概念和原理都和对象的解构赋值类似,这里就不在全部列举了。

  • 作者:weixin_34235371
  • 原文链接:https://blog.csdn.net/weixin_34235371/article/details/89016066
    更新时间:2022-07-20 10:19:12