我们先定义一个函数对象,并在这个函数的原型上添加属性
let o1={
a:1
};
function Fn(){
this.x=10;
}
Object.assign(Fn.prototype,o1);
let fn1=new Fn();
我们再添加一个可枚举属性,并添加get描述符
Object.defineProperty(fn1,"getA",{
enumerable: true, // 设为可枚举,不然 Object.assign 方法会过滤该属性
get(){
return "Could it return " + this.a
}
});
console.log(fn1.x);//10
console.log(fn1.a);//1
我们先用Object.assign()
来拷贝这个函数对象,看怎么样
let fn2=Object.assign({},fn1);
console.log(fn2.x);//10
console.log(fn2.a);//undefined
我们会发现原型上的a属性没有拷贝过来,因为Object.assing
是不能拷贝到继承或原型上的方法或者属性的,只能拷贝对象自身的属性
解决拷贝原型上的方法或者属性的两种方法
- 先获取原型上的属性,然后再创建一个有这个原型上的属性的对象,最后再将拷贝对象的自身属性拷贝到这个创建对象上
let proto=Object.getPrototypeOf(fn1);
let obj=Object.create(proto);
Object.assign(obj,fn1);
console.log(obj.x);//10
console.log(obj.a);//1
用Object.assign
不能正确拷贝get描述符,看obj的getA属性,只能获取值
console.log(obj);
console.log(obj)
所以我们推荐用第二种方法
- 直接创建一个对象,然后这个对象的原型就是获取拷贝对象的原型,自身属性就是拷贝对象上的自身属性
let obj2=Object.create(Object.getPrototypeOf(fn1),Object.getOwnPropertyDescriptors(fn1));
console.log(obj2.x);//10
console.log(obj2.a);//1
我们再看这个拷贝完的obj2,是否完全拷贝了函数对象
console.log(obj2);
console.log(obj2)
这种方法就可以正确的拷贝到了get描述符了
- 如果只是拷贝 自身可枚举属性,就可以只用
Object.assign
方法; - 如果是要拷贝原型上的属性,就需要
Object.assign
,Object.create
,Object.getPrototypeOf
方法结合使用 - 如果是拷贝
get /set
属性,就需要结合Ojbect.getOwnPropertyDescriptors
方法
网友评论