gpt4 book ai didi

带有循环引用的 Javascript 深度克隆对象

转载 作者:IT老高 更新时间:2023-10-28 23:16:02 25 4
gpt4 key购买 nike

我从 existing answer 复制了以下函数由德米特里皮丘金。这个函数可以在没有任何循环引用的情况下深度克隆一个对象——它可以工作。

function deepClone( obj ) {
if( !obj || true == obj ) //this also handles boolean as true and false
return obj;
var objType = typeof( obj );
if( "number" == objType || "string" == objType ) // add your immutables here
return obj;
var result = Array.isArray( obj ) ? [] : !obj.constructor ? {} : new obj.constructor();
if( obj instanceof Map )
for( var key of obj.keys() )
result.set( key, deepClone( obj.get( key ) ) );
for( var key in obj )
if( obj.hasOwnProperty( key ) )
result[key] = deepClone( obj[ key ] );
return result;
}

但是,我的程序无限循环,我意识到这是由于循环引用造成的。

循环引用示例:

function A() {}
function B() {}

var a = new A();
var b = new B();

a.b = b;
b.a = a;

最佳答案

现在有 structuredClone在 Web API 中也适用于循环引用。


上一个答案

我建议使用 Map 将源中的对象与目标中的副本映射。事实上,我最终使用了 WeakMap正如Bergi所建议的那样。只要源对象在映射中,就会返回其对应的副本,而不是进一步递归。

同时原deepClone代码中的部分代码可以进一步优化:

  • 原始值的第一部分测试有一个小问题:它将 new Number(1)new Number(2) 区别对待。这是因为第一个 if 中的 ==。应该改为===。但实际上,前几行代码似乎等同于这个测试:Object(obj) !== obj

  • 我还把一些 for 循环改写成更函数化的表达式

这需要 ES6 支持:

function deepClone(obj, hash = new WeakMap()) {
// Do not try to clone primitives or functions
if (Object(obj) !== obj || obj instanceof Function) return obj;
if (hash.has(obj)) return hash.get(obj); // Cyclic reference
try { // Try to run constructor (without arguments, as we don't know them)
var result = new obj.constructor();
} catch(e) { // Constructor failed, create object without running the constructor
result = Object.create(Object.getPrototypeOf(obj));
}
// Optional: support for some standard constructors (extend as desired)
if (obj instanceof Map)
Array.from(obj, ([key, val]) => result.set(deepClone(key, hash),
deepClone(val, hash)) );
else if (obj instanceof Set)
Array.from(obj, (key) => result.add(deepClone(key, hash)) );
// Register in hash
hash.set(obj, result);
// Clone and assign enumerable own properties recursively
return Object.assign(result, ...Object.keys(obj).map (
key => ({ [key]: deepClone(obj[key], hash) }) ));
}
// Sample data
function A() {}
function B() {}
var a = new A();
var b = new B();
a.b = b;
b.a = a;
// Test it
var c = deepClone(a);
console.log('a' in c.b.a.b); // true

关于带有循环引用的 Javascript 深度克隆对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40291987/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com