一、介绍:
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;