欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ES6——对象的解构赋值

程序员文章站 2022-07-02 10:37:34
...
对象的解构赋值,用于从一个现有的对象取值,将其中所有可遍历但尚未赋值的属性,分配到指定的对象上面,所有的键和他们的值都会“浅拷贝”到新对象上面。
//解构赋值
let {x,y,...z} = {x:1,y:2,a:3,b:4,c:{ca : 5}}
//结果如下:
x //1
y //2
z //{a:3,d:4,c:{ca:5}}

在上面的代码中,等号右边的对象的属性x,y,a,b,c都是可遍历的,但是x和y已经被读取,所以z接收的是剩下的几个属性。

需要注意的是,在进行对象的解构赋值时,语法上有如下要求:

1.  要求等号右边必须是对象。如果等号右边不是对象的话,编译器会尝试将等号右边的值转换为对象,如果转换失败的话,会返回运行时错误。根据JavaScript的类型转换知识,我们得出结论:如果在进行对象解构赋值时,等号右边是undefined和null的话,会报错,因为二者不能转换成对象。

// 因为转换对象失败,而报错的解构赋值
let { x, y, ...z } = null; // 运行时错误
let { x, y, ...z } = undefined; // 运行时错误
2. 要求解构赋值必须是最后一个参数,否则报错。

// 因为解构赋值不是最后一个参数而报错
let { ...x, y, z } = obj; // 句法错误
let { x, ...y, ...z } = obj; // 句法错误
再次强调:解构赋值是浅拷贝,如果键值是复合类型(数组、对象、函数),那么解构赋值拷贝的会是引用而不是值的副本。

// 解构赋值浅拷贝示例
let obj = {
   a : 1,
   b : {
      ba : 2
   }
}
let {...x} = obj;
obj.a.b.ba = 3;
x.a.b.ba  // 3;
在上述代码中,由于是浅拷贝的原因,更改obj对象的属性时,x的属性也同样被更改。再想的深入一些,浅拷贝同样不能拷贝到引用对象的原型链,x同样不会获得obj原型链上的属性。例子如下:
//解构赋值无法获取原型链上的属性
let obj = {
     a : 1,
     b : {
        ba : 2
     }
}
obj2 = {
    c : "属性c"
}
obj.prototype = obj2;
let {...x} = obj;
x.c  //undefined
对象的解构赋值应用范围很广,适配器模式就是其中一种应用范围。

所谓适配器模式,简言之,就是将一个类(对象)的接口(方法)转换成另外的一个接口,已解决类(对象)之间接口不兼容的问题的一种设计模式。

     假设我们现在有一个基础的类baseClass,baseClass有一个对外的接口名为 functionA。

// 基础类baseClass
class baseClass{
    //构造器
    constructor(){
       //基础类的构造器
    },
    //类的某些属性和方法,再次省略
    ...
    //类的对外接口A 
    functionA({a,b}){
       var {a1,b1} = {a,b};
       return a1 + b1;
    }
}

     这个类baseClass是我们之前工程的代码,接口 functionA 一直都很好用,但是某一天,我们的需求变了,需要我们为functionA 接口多传入两个新参数,进行更加复杂的运算。如果我们可以修改baseClass类的结构的话,我们可以添加一个新的接口。

// 基础类baseClass
class baseClass{
    //构造器
    constructor(){
       //基础类的构造器
    },
    //类的某些属性和方法,再次省略
    ...
    //类的对外接口A 
    functionA({a,b}){
       var {a1,b1} = {a,b};
       return a1 + b1;
    }
    functionB({a,b,c,d}){
       var {a1,b1,c1,d1} = {a,b,c,d};
       var tmp = c1 * d1;
       var tmp2 = this.functionA(a1,b1);
       return tmp1 + tmp2;
    }
}