我正在为一些特定于应用程序的对象编写一个简单的序列化/反序列化框架。
考虑以下:
"use strict"; function Dog(name) { this._name = name; }; Dog.prototype.constructor = Dog; Dog.prototype.getName = function() { return this._name; } var d1 = new Dog('fido'); var d2 = JSON.parse(JSON.stringify(d1)); // serialize / deserialize > d1 Dog { _name: 'fido' } > d1.getName() 'fido' > d2 { _name: 'fido' } > d2.getName() TypeError: d2.getName is not a function
在这一点上,我们可以问“这是什么d1有d2没有?”
d1
d2
一种可行的方法是手动将d1的方法分配给d2:
> d2.constructor = d1.constructor > d2.getName = d1.getName > d2.getName() 'fido'
这有两个缺点。首先,我必须手动将d1的每个方法分配给d2。其次,d2获得了自己的属性,并且不使用原型机制共享插槽:
> d2 Dog { _name: 'fido', constructor: [Function: Dog], getName: [Function] }
因此,我提出的问题是:给定一个对象(例如d2),是否可以将其与另一个对象(例如d1)的原型关联,以便它继承相同的行为?
Object.create()并且Object.getOwnPropertyDescriptors()是你所需要的。
Object.create()
Object.getOwnPropertyDescriptors()
const obj = JSON.parse(JSON.stringify(d1)) const d3 = Object.create(Dog.prototype, Object.getOwnPropertyDescriptors(obj))
此方法与OP方法之间的区别在于,此方法prototype在原型上设置属性,而OP方法直接在对象上设置属性。当您使用带有hasOwnProperty()方法的for- in循环遍历对象自身的属性时,可以看到以下内容:
prototype
hasOwnProperty()
for (const i in d1) { if (d3.hasOwnProperty(i)) { console.log(i) } }
在我的方法中,它仅输出_name,而在OP的方法中,它也输出getName。
_name
getName
不幸的是,它Object.getOwnPropertyDescriptors()是ECMAScript 2017的一部分,目前仅在Firefox中受支持,因此您需要使用Babel。
或者,您可以使用Object.setPrototypeOf()。它具有比更好的浏览器支持Object.getOwnPropertyDescriptors(),但是MDN不推荐使用它,因为它速度慢。
Object.setPrototypeOf()
const d3 = JSON.parse(JSON.stringify(d1)) Object.setPrototypeOf(d3, Dog.prototype)