ES6之Object.assign()用法详解

Object.assign()

介绍

该方法是ES6新增的接口,可以接收多个参数:第一个参数为目标对象,后边的参数为源对象;其作用是用来合并多个js对象:将多个源对象合并到目标对象上,如果出现同名的属性(方法)后合并的会覆盖掉之前合并的同名属性(方法)。也就是后边的优先级更高一点。assign不会合并不可枚举的属性

demo

let target = {
    
     a: 1 };
let source1 = {
    
     b: 2 };
let source2 = {
    
     c: 3 };
let source3 = {
    
     b: 4 };
console.log(Object.assign(target, source1, source2, source3));
// { a: 1, b: 4, c: 3 }

问题

问题1:参数类型问题

Object.assign()设计的主要目的是用来合并对象,所以理论上它接收到的参数是对象类型;如果参数不是对象类型则先转换成对象类型然后进行合并。

注意

  • target 如果不是对象,则转换成对象;如果不能转换,就报错
  • source 如果不是对象,则转换成对象;如果不能转换,则忽略
  • null、undefined不能转换成对象类型
let target = {
    
    };
let source1 = 'abc';
let source2 = null;
let source3 = {
    
     "2": 4 };
console.log(Object.assign(target, source1, source2, source3));
// { '0': 'a', '1': 'b', '2': 4 }

问题2:拷贝属性限制

Object.assign拷贝的属性是有限制的,只会拷贝对象本身的属性(不会拷贝继承属性),也不会拷贝不可枚举的属性。但是属性名为Symbol值的属性,是可以被Object.assign拷贝的。

问题3:拷贝是深拷贝?浅拷贝?

Object.assign进行的拷贝是浅拷贝。也就是说,如果拷贝过来的属性的值是对象等复合属性,那么只能拷贝过来一个引用。

const obj1 = {
    
    a: {
    
    b: 1}};
const obj2 = Object.assign({
    
    }, obj1);
 
obj1.a.b = 2;
obj2.a.b // 2

应用场景

1、为对象添加属性

class Point{
   constructor(x,y){
      Object.assign(this,{x,y});
   }
}

上面的方法可以为对象Point类的实例对象添加属性x和属性y。

2、为对象添加方法

// 方法也是对象
// 将两个方法添加到类的原型对象上
// 类的实例会有这两个方法
Object.assign(SomeClass.prototype,{
    someMethod(arg1,arg2){...},
    anotherMethod(){...}
});

将方法添加到类的原型对象上后,类的实例能继承这两个方法。

3、克隆对象

//克隆对象的方法
function clone(origin){
    //获取origin的原型对象
    let originProto = Obejct.getPrototypeOf(origin);
    //根据原型对象,创建新的空对象,再assign
    return Object.assign(Object.create(originProto),origin);
}

4、为属性指定默认值

// 默认值对象
const DEFAULTS = {
   logLevel : 0,
   outputFormat : 'html'
};
 
// 利用assign同名属性会覆盖的特性,指定默认值,如果options里有新值的话,会覆盖掉默认值
function processContent(options){
   options = Object.assign({},DEFAULTS,options);
   console.log(options);
   //...
}

处于assign浅拷贝的顾虑,DEFAULTS对象和options对象此时的值最好都是简单类型的值,否则函数会失效。

const DEFAULTS = {
  url: {
    host: 'example.com',
    port: 7070
  },
};
 
processContent({ url: {port: 8000} })
// {
//   url: {port: 8000}
// }

上面的代码,由于url是对象类型,所以默认值的url被覆盖掉了,但是内部缺少了host属性,形成了一个bug。

补充

转对象

扫描二维码关注公众号,回复: 15899269 查看本文章
Object(true)  // {[[PrimitiveValue]]: true}
Object(10)    // {[[PrimitiveValue]]: 10}
Object('abc') // {0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"}

猜你喜欢

转载自blog.csdn.net/weixin_45268025/article/details/123925407
今日推荐