在我正在进行的项目中,我不得不将对象克隆到变量中.
我第一次尝试 - 似乎是最明显的解决方案 - var obj2 = obj1
然而我很快意识到这使得obj2 引用 obj1,所以每当我在obj2中设置属性时,属性也会在obj1中更新.好吧,我不能那样.所以,我开始寻找在JavaScript中克隆对象的方法 - 我发现了多个解决方案,主要是
var obj2 = JSON.parse(JSON.stringify(obj1))
- 但这并没有保留我为我的对象定义的所有getter和setter!
对我来说现在最明显的解决方案似乎首先使用上面的JSON技巧使obj2具有所有obj1的属性,然后循环遍历所有对象getter和setter并使用它们添加它们Object.defineProperty()
,但我还没有找到一种方法来获取一个对象的所有getter/setter.
在实际层面上,100%准确地克隆对象是不可能的,因为getter和setter(实际上是其他函数)可能通过闭包访问词法范围的私有变量.访问这样的方法将引用原始对象,而不是克隆.
如果(并且仅当)不是这种情况,您可以枚举通过所有属性(甚至是非可枚举的属性)Object.getOwnPropertyNames()
,然后为每个名称简单地获取个体PropertyDescriptors
,Object.getOwnPropertyDescriptor
然后将结果字段传递给Object.defineProperty
,例如:
function shallowClone(obj) { var clone = Object.create(Object.getPrototypeOf(obj)); var props = Object.getOwnPropertyNames(obj); props.forEach(function(key) { var desc = Object.getOwnPropertyDescriptor(obj, key); Object.defineProperty(clone, key, desc); }); return clone; }
在ES2017中,您可以这样做:
function shallowClone(obj) { return Object.create( Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj) ); }