使用 Object.create 执行的浅层克隆如何与描述符、setter/getter 一起使用?

如何解决使用 Object.create 执行的浅层克隆如何与描述符、setter/getter 一起使用?

根据此source

要制作“真实副本”(克隆),我们可以使用... 所谓的“浅拷贝”(通过引用复制嵌套对象) 或“深度克隆”功能

因此,就我所知,浅层克隆假设如果内部还有其他内部对象,则它们将通过引用进行复制。他们没有克隆。

好吧,复制对象的所有内部属性是如何发生的,例如描述符、getter/setter。它们是通过引用复制的吗?

解决方法

考虑浅克隆一个只有一个原始属性的标准对象时所采取的基于 ES3 的步骤:

  1. 创建一个新的空对象。
  2. 为该空对象添加一个键。
  3. 为该键分配一个值。
  4. 返回对象。

这些步骤可以使用手动功能完成,如下所示:

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 的步骤:

  1. 创建一个新的空对象。
  2. 从传入的对象中获取一个包含描述符的数组。
  3. “浅克隆”一个描述符,然后应用描述符克隆你的空对象。
  4. 返回对象。

例如:

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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?