ES6-Object.assign

286 阅读2分钟

一、介绍:

ES6提供了Object.assign(),用于合并/复制对象的属性。

let newObject = Object.assign(target, source_1, ..., source_n)

它会修改target对象,然后将它返回:先将source_1对象的所有可枚举属性复制给target,然后依次复制source_1等的属性。

二、常见用法:

1、初始化对象属性

// 传统写法:
class Point {
   constructor(x, y) {
       this.x = x;
       this.y = y;
   }
}
// 使用assign
class Point {
   constructor(x, y){
       Object.assign(this, { x, y });
   }
}

2、为对象添加方法

// 老方式:
MyClass.prototype.foo = function(arg1, arg2)
{
   //...
};
// 使用assign

Object.assign(MyClass.prototype, {
   foo(arg1, arg2)
   {
       //...
   }
});

3、复制对象

newObject 和 target 共用一个内存空间,会相互引用(坑点)。

示例1、

返回结果


示例2、

返回结果

3.1、实际使用-扩展

// 实际使用
let a = {name:'lxq',age:28};
let b = {saySotry(){console.log('hi, my name is ' + this.name)}};
 a = Object.assign(a,b);
a.saySotry();
// hi, my name is lxq

3.2、实际使用-复制(不复制原型链)

// 不复制原型链  构造函数写法
var Point = function(x)
{
   this.x = x;
}
Point.prototype.y = 2;
var obj = new Point(1);
var copy = Object.assign({}, obj); 
console.log(copy) 
// 输出{x:1}

3.3、实际使用-复制(原型链)

// 复制包含其原型链  构造函数写法
var Point = function(x)
{
   this.x = x;
}
Point.prototype.y = 2;
var obj = new Point(1);
var copy = Object.assign({ __proto__: obj.__proto__ }, obj); // 输出{x:1,y:2} 
console.log(copy) 
// 输出{x:1,y:2}

3.4、结论:

Object.assgin 只拷贝第一层, copy和target引用,共用内存。


三、与扩展运算符的关系

扩展运算符是拷贝第一层, 新生成的对象和合并的对象无引用关系。

1、基本示例

let a = {a:1,c:4,f:{g:10}};
let b = {a:2,b:2,f:{h:11}};
let c = {...a,...b};
c.d = 5;
a.e = 6;
console.log('a========',a);
console.log('b========',b);
console.log('c========',c);

返回结果:

2、合并包含其原型链

var Point = class {
    constructor(age,name){
        this.age = age;
        this.name = name;
    }
    sayStory(){
        console.log('hi,my name is'+ this.age);
    }

}
var obj = new Point(1);
var obj1 = {__proto__:obj.__proto__,...obj};
obj1.x = 2;
console.log('obj======',obj);
console.log('obj1======',obj1);

返回结果:

四、手写-浅比较

function is (x, y) {
    return (
        (x === y && (x !== 0 || 1/x === 1/y) || (x !== x && y!==y))
    );
}
const objectIs = typeof Object.is === 'function' ? Object.is : is;
const hasOwnProperty = Object.prototype.hasOwnProperty;

function shallowEqual (objA, objB) {
    if(objectIs(objA, objB)) {
        return true;
    }
  
    if(
        typeof objA !== 'object' || 
        objA === null ||
        typeof objB !== 'object' || 
        objB === null
    ){
        return false;  
    }
  
    const keysA = Object.keys(objA);
    const keysB = object.keys(objB);
  
    if(keysA.length !== keysB.length) {
        return false;
    }
  // test for A's keys different from B.
  for (let i = 0; i < keysA.length; i++ ){
    if(
        !hasOwnProperty.call(objB, keysA[i]) ||
        !objectIs(objA[keysA[i]], objB[keysA[i]])
    ){
        return false;
    }
  }
  
  return true;
}

export default shallowEqual;