javascript—使用object.create执行的浅层克隆如何使用描述符、setter/getter?

w8rqjzmb  于 2021-09-08  发布在  Java
关注(0)|答案(1)|浏览(390)

根据这一消息来源:
要制作“真实副本”(克隆),我们可以使用。。。对于所谓的“浅复制”(通过引用复制嵌套对象)或“深度克隆”功能。
因此,据我所知,浅层克隆假设,如果内部有其他内部对象,那么它们将通过引用进行复制。他们不能克隆。
那么,对象的所有内部属性(例如描述符、getter/setter)是如何进行复制的呢。它们是通过引用复制的吗?

tkqqtvp1

tkqqtvp11#

考虑当浅克隆一个只有一个原始属性的标准对象时所采取的基于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);

assign({},obj)是(自2009年es5发布以来)生成与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, key, descriptors[key] ); // 3

    return cloneOfObj; // 4
}

首先,我们将定义一个构造函数,它可以生成具有不可枚举属性和原型的对象:

function objConstructor(){

    let someDescriptor = {
        'a': {
            value: 'b',
            writable: true,
            configurable:true,
            enumerable:false
        };
    }

    let returnObj = Object.create( {}, someDescriptor );
}
objConstructor.prototype.extraInfo = “javascript rocks”;

然后,我们将使用该构造函数创建一个奇特的新对象:

let constructedObj = new objConstructor();

现在,我们可以克隆这个建筑北京,在它所有的荣耀中,因此:

let newCon = es5ShallowCloneWithPrototype(constructedObj);

或者,我们可以利用es5为我们带来的内置魔法克隆我们的constructedobj,让它焕然一新:

let newCon2 = Object.create(
    Object.getPrototypeOf(constructedObj),
    Object.getOwnPropertyDescriptors(constructedObj)
);

///////////////////////////////////////////////
希望这个小小的概述有助于澄清描述符的处理方式与克隆过程中处理常规ol对象的方式不同。
要更仔细地查看es3或es5中的克隆函数可用的信息,并查看getter和对象值在枚举期间的显示方式,请查看以下codepen链接,然后打开浏览器的控制台。。。您可能希望清除控制台,然后再次单击run按钮以查看捕获信息的最佳表示形式。ps:使用es3样式的克隆,setter的名称将添加到克隆中,并保留undefined的值。使用es5风格的克隆时,如果getter和setter引用非克隆器可访问范围中的值,则getter和setter可能会导致错误。)
https://codepen.io/ed_johnsen/pen/grmjajr
都是好事。

相关问题