如果克隆数组,我将使用 cloneArr = arr.slice()
我想知道如何在nodejs中克隆对象。
Answers:
对于不需要压缩每一滴性能的实用程序和类,我经常作弊,只是使用JSON执行深层复制:
function clone(a) {
return JSON.parse(JSON.stringify(a));
}
这不是唯一的答案,也不是最优雅的答案。所有其他答案都应考虑成为生产瓶颈。但是,这是一个快速而肮脏的解决方案,非常有效,并且在大多数情况下(我会克隆属性的简单哈希值)很有用。
newObj = obj.clone(args...);
在以上任何答案中均未提及Object.assign。
let cloned = Object.assign({}, source);
如果您使用的是ES6,则可以使用传播运算符:
let cloned = { ... source };
参考:https : //developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
let a = {x:1}; let b = Object.assign({}, a); a.x = 2; a.y = 1; console.log(a, b);
如果不想“自己动手”,这里有一些Node模块。这个看起来不错:https://www.npmjs.com/package/clone
看起来它可以处理各种内容,包括循环引用。从github页面:
clone master克隆对象,数组,Date对象和RegEx对象。一切都是递归克隆的,例如,您可以在对象数组中克隆日期。[...]循环引用?是的
进行通用但有用的克隆操作很困难,因为应该递归克隆哪些内容以及应该复制哪些内容取决于特定对象的工作方式。
可能有用的是
function clone(x)
{
if (x === null || x === undefined)
return x;
if (typeof x.clone === "function")
return x.clone();
if (x.constructor == Array)
{
var r = [];
for (var i=0,n=x.length; i<n; i++)
r.push(clone(x[i]));
return r;
}
return x;
}
在这段代码中,逻辑是
null或undefined仅返回相同的值(需要特殊情况,因为尝试查看是否存在clone方法是错误的)clone方法吗?然后用那个此克隆功能应允许轻松实现自定义克隆方法……例如
function Point(x, y)
{
this.x = x;
this.y = y;
...
}
Point.prototype.clone = function()
{
return new Point(this.x, this.y);
};
function Polygon(points, style)
{
this.points = points;
this.style = style;
...
}
Polygon.prototype.clone = function()
{
return new Polygon(clone(this.points),
this.style);
};
当在对象中知道特定数组的正确克隆操作只是浅表副本时,可以调用values.slice()而不是clone(values)。
例如,在上面的代码中,我明确要求克隆多边形对象将克隆点,但将共享相同的样式对象。如果我也想克隆样式对象,那么我可以通过clone(this.style)。
.clone方法。这是处理克隆对象的最佳方法。
if (x.clone)应该是if (typeof x.clone === 'function')
没有用于克隆对象的本机方法。下划线工具_.clone是一个浅表克隆。
_.clone = function(obj) {
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
};
它可以切片或扩展它。
这是 _.extend
// extend the obj (first parameter)
_.extend = function(obj) {
// for each other parameter
each(slice.call(arguments, 1), function(source) {
// loop through all properties of the other objects
for (var prop in source) {
// if the property is not undefined then add it to the object.
if (source[prop] !== void 0) obj[prop] = source[prop];
}
});
// return the object (first parameter)
return obj;
};
扩展简单地遍历所有项目,并创建一个包含项目的新对象。
您可以根据需要推出自己的幼稚实现
function clone(o) {
var ret = {};
Object.keys(o).forEach(function (val) {
ret[val] = o[val];
});
return ret;
}
有充分的理由要避免深度克隆,因为无法克隆闭包。
我个人已经问过一个问题deep cloning objects before,得出的结论是您只是不这样做。
我的建议是使用underscore,它是_.clone浅克隆的方法
这是个老问题,但答案比迄今为止建议的要优雅得多。使用内置的utils._extend:
var extend = require("util")._extend;
var varToCopy = { test: 12345, nested: { val: 6789 } };
var copiedObject = extend({}, varToCopy);
console.log(copiedObject);
// outputs:
// { test: 12345, nested: { val: 6789 } }
请注意,第一个参数与空对象{}一起使用-这告诉我们扩展了复制的对象需要复制到新对象。如果将现有对象用作第一个参数,则第二个(以及所有后续)参数将在第一个参数变量上进行深度合并复制。
使用上面的示例变量,您还可以执行以下操作:
var anotherMergeVar = { foo: "bar" };
extend(copiedObject, { anotherParam: 'value' }, anotherMergeVar);
console.log(copiedObject);
// outputs:
// { test: 12345, nested: { val: 6789 }, anotherParam: 'value', foo: 'bar' }
非常方便的实用程序,尤其是在我习惯于在AngularJS和jQuery中进行扩展的地方。
希望这对别人有帮助;对象引用覆盖是一种苦难,这每次都能解决!
根据要对克隆对象进行的操作,可以利用javascript的原型继承机制,并通过以下方式实现某种程度的克隆对象:
var clonedObject = Object.create(originalObject);
请记住,这不是完整的克隆-更好或更坏。
这样做的好处是,您实际上没有复制对象,因此内存占用空间很低。
关于此方法,需要记住一些棘手的事情:原型链中定义的属性的迭代有时会有所不同,并且对原始对象的任何更改也会影响克隆的对象,除非该属性本身也已设置。 。
var a = {foo: "bar"}, b = Object.create(a); a.foo = "broken"; console.log(b.foo); // "broken";
b.foo = "working"; console.log(a.foo); // still "broken";当然必须意识到原始对象的更改将反映在“克隆”中,而“克隆”中的更改将不会反映在原始对象中,但是我不会说这很危险–这一切都取决于您要对克隆做什么
我实现了完整的深层副本。我相信它是通用克隆方法的最佳选择,但它不能处理循环引用。
parent = {'prop_chain':3}
obj = Object.create(parent)
obj.a=0; obj.b=1; obj.c=2;
obj2 = copy(obj)
console.log(obj, obj.prop_chain)
// '{'a':0, 'b':1, 'c':2} 3
console.log(obj2, obj2.prop_chain)
// '{'a':0, 'b':1, 'c':2} 3
parent.prop_chain=4
obj2.a = 15
console.log(obj, obj.prop_chain)
// '{'a':0, 'b':1, 'c':2} 4
console.log(obj2, obj2.prop_chain)
// '{'a':15, 'b':1, 'c':2} 4
此代码使用其原型复制对象,还复制函数(可能对某人有用)。
function copy(obj) {
// (F.prototype will hold the object prototype chain)
function F() {}
var newObj;
if(typeof obj.clone === 'function')
return obj.clone()
// To copy something that is not an object, just return it:
if(typeof obj !== 'object' && typeof obj !== 'function' || obj == null)
return obj;
if(typeof obj === 'object') {
// Copy the prototype:
newObj = {}
var proto = Object.getPrototypeOf(obj)
Object.setPrototypeOf(newObj, proto)
} else {
// If the object is a function the function evaluate it:
var aux
newObj = eval('aux='+obj.toString())
// And copy the prototype:
newObj.prototype = obj.prototype
}
// Copy the object normal properties with a deep copy:
for(var i in obj) {
if(obj.hasOwnProperty(i)) {
if(typeof obj[i] !== 'object')
newObj[i] = obj[i]
else
newObj[i] = copy(obj[i])
}
}
return newObj;
}
有了这个副本,我无法找到原始副本和复制副本之间的任何区别,除非原始副本在其构造上使用了闭包,所以我认为它是一个很好的实现。
希望对您有所帮助