如何解决使用 Object.create 执行的浅层克隆如何与描述符、setter/getter 一起使用?
根据此source:
要制作“真实副本”(克隆),我们可以使用... 所谓的“浅拷贝”(通过引用复制嵌套对象) 或“深度克隆”功能。
因此,就我所知,浅层克隆假设如果内部还有其他内部对象,则它们将通过引用进行复制。他们没有克隆。
好吧,复制对象的所有内部属性是如何发生的,例如描述符、getter/setter。它们是通过引用复制的吗?
解决方法
考虑浅克隆一个只有一个原始属性的标准对象时所采取的基于 ES3 的步骤:
- 创建一个新的空对象。
- 为该空对象添加一个键。
- 为该键分配一个值。
- 返回对象。
这些步骤可以使用手动功能完成,如下所示:
function es3ShallowClone(incomingObj){
var cloneOfObj = {}; // 1
for(var key in incomingObj)
cloneOfObj[key] = incomingObj[key]; // 2 and 3
return cloneOfObj; // 4
}
使用 es3ShallowClone 函数,您可以这样进行克隆:
var obj = {a:"b"};
var newObj = es3ShallowClone(obj);
Object.assign( {},obj ) 是(自 ES5 发布以来,在 2009 年)一种生成与 es3ShallowClone 生成相同输出的内置方法:
let newAssignedObj = Object.assign( {},obj );
Object.assign 仅复制可枚举的属性,并且 Object.assign 不传输原型。
/////////////////////////////////////////////
欲了解更多“权力:” 如果您希望克隆具有不可枚举属性的其他标准对象,则需要使用 Object.getOwnPropertyDescriptors 和 Object.defineProperty;可能与 Object.create 一起使用。
手动浅克隆具有不可枚举属性的其他标准对象时采取的基于 ES5 的步骤:
- 创建一个新的空对象。
- 从传入的对象中获取一个包含描述符的数组。
- “浅克隆”一个描述符,然后应用描述符克隆你的空对象。
- 返回对象。
例如:
function es5ShallowClone(incomingObj){
let cloneOfObj = {}; // 1
let descriptors = Object.getOwnPropertyDescriptors(incomingObj); // 2
for(var key in descriptors)
Object.defineProperty( cloneOfObj,key,descriptors[key] ); // 3
return cloneOfObj; // 4
}
首先,让我们制作一个具有不可枚举属性的示例对象:
制作描述符:
let someDescriptor = {
'a': {
value: 'b',writable: true,configurable:true,enumerable:false
};
创建一个对象并为其分配描述符:
let obj2 = Object.create( {},someDescriptor );
然后克隆它:
let newObj2 = es5ShallowClone(obj2);
代替 es5ShallowClone,你可以这样写:
let newObjToo = Object.create( {},Object.getOwnPropertyDescriptors(obj2) );
/////////////////////////////////////////////
为了获得更多的“力量”,您还需要转移原型;请注意,我对“传输”一词的使用有点笨拙,因为原型并没有离开原始对象……两个对象最终都引用了同一个原型。
我们需要对 es5ShallowClone 函数进行的唯一更改是步骤 1;以便它根据传入对象的原型创建一个对象:
function es5ShallowCloneWithPrototype(incomingObj){
let cloneOfObj = new incomingObj.constructor(); // 1
let descriptors = Object.getOwnPropertyDescriptors(incomingObj); // 2
for(var key in descriptors)
Object.defineProperty( cloneOfObj,descriptors[key] ); // 3
return cloneOfObj; // 4
}
首先,我们将定义一个构造函数,它可以创建一个具有不可枚举属性和原型的对象:
function objConstructor(){
let someDescriptor = {
'a': {
value: 'b',enumerable:false
};
}
let returnObj = Object.create( {},someDescriptor );
}
objConstructor.prototype.extraInfo = “javascript rocks”;
然后我们将使用该构造函数来创建一个漂亮的新对象:
let constructedObj = new objConstructor();
现在,我们可以克隆这个构建的Obj,在它的所有荣耀中,因此:
let newCon = es5ShallowCloneWithPrototype(constructedObj);
或者,我们可以使用 ES5 为我们带来的内置魔法,克隆我们的构建对象:
let newCon2 = Object.create(
Object.getPrototypeOf(constructedObj),Object.getOwnPropertyDescriptors(constructedObj)
);
/////////////////////////////////////////////
希望这个小小的概述有助于澄清描述符的处理方式与克隆过程中处理常规 ol 对象的方式不同。
要仔细查看 ES3 或 ES5 之后的克隆函数可用的信息,并查看在枚举过程中如何呈现 getter 和对象值,请查看以下 codepen 链接,并打开浏览器的控制台。 .. 您可能想要清除控制台,然后再次单击运行按钮以查看捕获信息的最佳表示。 PS:使用 ES3 风格的克隆,setter 的名称被添加到你的克隆中并保持 undefined 的值。使用 ES5 样式的克隆时,如果 getter 和 setter 引用非克隆可访问范围中的值,则 getter 和 setter 可能会导致错误。)
https://codepen.io/Ed_Johnsen/pen/GRmjajr
一切美好。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。