如何在保留getter/setter的同时浅层复制Javascript对象?
背景(为什么如何在保留getter/setter的同时浅层复制Javascript对象?,javascript,Javascript,背景(为什么Object.update()或jQuery.extend()不是解决方案,为什么这不是其他how-to-copy-a-javascript-Object问题的重复): 此版本的复制,使用for循环 function copy_obj(obj) { var copy = {}; for (var attr in obj) if (obj.hasOwnProperty(attr)) { copy[attr] = obj[attr]; }
Object.update()
或jQuery.extend()
不是解决方案,为什么这不是其他how-to-copy-a-javascript-Object问题的重复):
此版本的复制,使用for循环
function copy_obj(obj) {
var copy = {};
for (var attr in obj) if (obj.hasOwnProperty(attr)) {
copy[attr] = obj[attr];
}
return copy;
}
仅复制属性值(与Object.update()
)一样),并且在以下对象上失败:
var myobj = {
_fname: 'fname',
_lname: 'lname',
get fullname() { return this._fname + ' ' + this._lname; },
set fullname(v) { this._fname = v; }
};
i、 e
当
问题:我发现我需要使用getOwnPropertyNames/Descriptor来获取/设置描述符,但我还没有找到任何简单的方法来确定某个内容是否只是可以直接复制的普通值——if语句中的内容:
function copy_obj2(obj) {
var mycopy = {};
Object.getOwnPropertyNames(obj).forEach(function (prop) {
var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
if (/* descriptor is a plain value */) {
mycopy[prop] = obj[prop];
} else {
Object.defineProperty(mycopy, prop, descriptor);
}
});
return mycopy;
}
(我只对复制类似对象的值感兴趣,而不是数组或其他基本类型)。您不需要担心描述符的类型;无论它是数据类型描述符还是访问器类型描述符,都可以按原样使用它在目标对象上创建属性
function copy_obj2(obj) {
var mycopy = {};
Object.getOwnPropertyNames(obj).forEach(function (prop) {
var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
Object.defineProperty(mycopy, prop, descriptor);
});
return mycopy;
}
但是您也可以使用
getOwnPropertyDescriptors
,使用defineProperties
:
function copy_obj2(obj) {
return Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj));
}
如果还希望在克隆中包含原型,则:
function copy_obj2(obj) {
return Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
}
但是,
getOwnPropertyDescriptors
在IE中不可用。建议使用polyfill。为什么您会关心它是哪种描述符<代码>对象。定义属性也可用于创建数据属性。提示:“普通”描述符有可写
和值
字段,无获取
或设置
字段。数据描述符/属性的开销不是比普通值大得多吗?除了有一个值,没有get/set,我是否也不需要检查可枚举/可写/可配置?…当它是可枚举、可写和可配置的,并且目标没有继承setter时;但我认为,当您想要复制getter/setter时,您也想要复制这些其他属性。getOwnPropertyDescriptors
在Chrome/FF上也是最近才出现的,因此如果不添加polyfill,我可能无法使用它。。
function copy_obj2(obj) {
return Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj));
}
function copy_obj2(obj) {
return Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
}