在Node.js中克隆对象

2020/10/16 07:21 · javascript ·  · 0评论

在node.js中克隆对象的最佳方法是什么

例如,我想避免以下情况:

var obj1 = {x: 5, y:5};
var obj2 = obj1;
obj2.x = 6;
console.log(obj1.x); // logs 6

该对象很可能包含复杂类型作为属性,因此无法解决简单的for(obj1中的var x)。我需要自己编写一个递归克隆,还是内置一些我看不到的东西?

可能性1

简洁的深层副本:

var obj2 = JSON.parse(JSON.stringify(obj1));

可能性2(已弃用)

注意:此解决方案现在在Node.js文档中标记为已弃用

从未打算在内部Node.js模块外部使用util._extend()方法。社区仍然找到并使用了它。

它已被弃用,不应在新代码中使用。JavaScript通过Object.assign()具有非常相似的内置功能。

原始答案

对于浅表副本,请使用Node的内置util._extend()功能。

var extend = require('util')._extend;

var obj1 = {x: 5, y:5};
var obj2 = extend({}, obj1);
obj2.x = 6;
console.log(obj1.x); // still logs 5

Node_extend函数的源代码在这里:https : //github.com/joyent/node/blob/master/lib/util.js

exports._extend = function(origin, add) {
  // Don't do anything if add isn't an object
  if (!add || typeof add !== 'object') return origin;

  var keys = Object.keys(add);
  var i = keys.length;
  while (i--) {
    origin[keys[i]] = add[keys[i]];
  }
  return origin;
};

我很惊讶Object.assign没有被提及。

let cloned = Object.assign({}, source);

如果可用(例如Babel),则可以使用对象传播运算符

let cloned = { ... source };
Object.defineProperty(Object.prototype, "extend", {
    enumerable: false,
    value: function(from) {
        var props = Object.getOwnPropertyNames(from);
        var dest = this;
        props.forEach(function(name) {
            if (name in dest) {
                var destination = Object.getOwnPropertyDescriptor(from, name);
                Object.defineProperty(dest, name, destination);
            }
        });
        return this;
    }
});

这将定义您可以使用的扩展方法。代码来自本文。

var obj2 = JSON.parse(JSON.stringify(obj1));

您可以使用JQuery的扩展功能:

var newClone= jQuery.extend({}, oldObject);  
var deepClone = jQuery.extend(true, {}, oldObject); 

也有一个Node.js插件:

https://github.com/shimondoodkin/nodejs-clone-extend

要在没有JQuery或插件的情况下进行阅读,请在此处阅读:

http://my.opera.com/GreyWyvern/blog/show.dml/1725165

查看underscore.js它具有克隆扩展功能,以及许多其他非常有用的功能。

这可能很有用:将Underscore模块与Node.js一起使用

如果不想“自己动手”,这里有一些Node模块。这个看起来不错:https//www.npmjs.com/package/clone

看起来它可以处理各种内容,包括循环引用。github页面:

clone master克隆对象,数组,Date对象和RegEx对象。一切都是递归克隆的,因此,例如,您可以在对象数组中克隆日期。[...]循环引用?是的

这段代码也起作用,因为Object.create()方法使用指定的原型对象和属性创建一个新对象。

var obj1 = {x:5, y:5};

var obj2 = Object.create(obj1);

obj2.x; //5
obj2.x = 6;
obj2.x; //6

obj1.x; //5

在NodeJS中克隆对象的简单,最快的方法是使用Object.keys(obj)方法

var a = {"a": "a11", "b": "avc"};
var b;

for(var keys = Object.keys(a), l = keys.length; l; --l)
{
   b[ keys[l-1] ] = a[ keys[l-1] ];
}
b.a = 0;

console.log("a: " + JSON.stringify(a)); // LOG: a: {"a":"a11","b":"avc"} 
console.log("b: " + JSON.stringify(b)); // LOG: b: {"a":0,"b":"avc"}

方法Object.keys需要JavaScript 1.8.5; nodeJS v0.4.11支持此方法

但是对于嵌套对象,当然需要实现递归函数


另一种解决方案是使用本机JSON(在JavaScript 1.7中实现),但比上一个慢得多(慢10倍)。

var a = {"a": i, "b": i*i};
var b = JSON.parse(JSON.stringify(a));
b.a = 0;

Github上还有一个项目,旨在成为更直接的港口jQuery.extend()

https://github.com/dreamerslab/node.extend

一个例子,从jQuery docs修改而来

var extend = require('node.extend');

var object1 = {
    apple: 0,
    banana: {
        weight: 52,
        price: 100
    },
    cherry: 97
};

var object2 = {
    banana: {
        price: 200
    },
    durian: 100
};

var merged = extend(object1, object2);

你们都很痛苦,但解决方案很简单。

var obj1 = {x: 5, y:5};

var obj2 = {...obj1}; //景气

还有另一个库lodash,它具有clonecloneDeep,还有许多其他有用的功能。

在寻找真正的克隆选项时,我偶然发现了ridcully的链接:

http://my.opera.com/GreyWyvern/blog/show.dml/1725165

我修改了该页面上的解决方案,以使附加到Object原型的功能无法枚举。这是我的结果:

Object.defineProperty(Object.prototype, 'clone', {
    enumerable: false,
    value: function() {
        var newObj = (this instanceof Array) ? [] : {};
        for (i in this) {
        if (i == 'clone') continue;
            if (this[i] && typeof this[i] == "object") {
                newObj[i] = this[i].clone();
            } else newObj[i] = this[i]
        } return newObj;
    }
});

希望这对其他人也有帮助。请注意,有一些警告...尤其是对于名为“ clone”的属性。这对我来说很好。我不写任何功劳。同样,我只更改了定义方式。

您还可以在NodeJS中使用SugarJS。

http://sugarjs.com/

它们具有非常干净的克隆功能:http :
//sugarjs.com/api/Object/clone

如果您使用的是咖啡脚本,则非常简单:

newObject = {}
newObject[key] = value  for own key,value of oldObject

虽然这不是很深的克隆。

没有一个答案让我满意,有几个没有用,或者仅仅是浅表克隆,来自@ clint-harris并使用JSON.parse / stringify的答案很好,但是很慢。我发现了一个可以快速进行深度克隆的模块:https : //github.com/AlexeyKupershtokh/node-v8-clone

在node.js中没有内置的方法可以对对象进行真实的克隆(深拷贝)。有一些棘手的情况,因此您绝对应该为此使用一个库。我为我的simpleoo编写了这样的函数如果deepCopy不需要,您可以使用该函数,而无需使用库中的任何其他函数(该函数很小)。该函数支持克隆多种数据类型,包括数组,日期和正则表达式,它支持递归引用,并且还可以与构造函数具有必需参数的对象一起使用。

这是代码:

//If Object.create isn't already defined, we just do the simple shim, without the second argument,
//since that's all we need here
var object_create = Object.create;
if (typeof object_create !== 'function') {
    object_create = function(o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}

/**
 * Deep copy an object (make copies of all its object properties, sub-properties, etc.)
 * An improved version of http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
 * that doesn't break if the constructor has required parameters
 * 
 * It also borrows some code from http://stackoverflow.com/a/11621004/560114
 */ 
function deepCopy = function deepCopy(src, /* INTERNAL */ _visited) {
    if(src == null || typeof(src) !== 'object'){
        return src;
    }

    // Initialize the visited objects array if needed
    // This is used to detect cyclic references
    if (_visited == undefined){
        _visited = [];
    }
    // Ensure src has not already been visited
    else {
        var i, len = _visited.length;
        for (i = 0; i < len; i++) {
            // If src was already visited, don't try to copy it, just return the reference
            if (src === _visited[i]) {
                return src;
            }
        }
    }

    // Add this object to the visited array
    _visited.push(src);

    //Honor native/custom clone methods
    if(typeof src.clone == 'function'){
        return src.clone(true);
    }

    //Special cases:
    //Array
    if (Object.prototype.toString.call(src) == '[object Array]') {
        //[].slice(0) would soft clone
        ret = src.slice();
        var i = ret.length;
        while (i--){
            ret[i] = deepCopy(ret[i], _visited);
        }
        return ret;
    }
    //Date
    if (src instanceof Date) {
        return new Date(src.getTime());
    }
    //RegExp
    if (src instanceof RegExp) {
        return new RegExp(src);
    }
    //DOM Element
    if (src.nodeType && typeof src.cloneNode == 'function') {
        return src.cloneNode(true);
    }

    //If we've reached here, we have a regular object, array, or function

    //make sure the returned object has the same prototype as the original
    var proto = (Object.getPrototypeOf ? Object.getPrototypeOf(src): src.__proto__);
    if (!proto) {
        proto = src.constructor.prototype; //this line would probably only be reached by very old browsers 
    }
    var ret = object_create(proto);

    for(var key in src){
        //Note: this does NOT preserve ES5 property attributes like 'writable', 'enumerable', etc.
        //For an example of how this could be modified to do so, see the singleMixin() function
        ret[key] = deepCopy(src[key], _visited);
    }
    return ret;
};
npm install node-v8-clone

最快的克隆器,它从node.js打开本机克隆方法

var clone = require('node-v8-clone').clone;
var newObj = clone(obj, true); //true - deep recursive clone

另一种解决方案是使用以下方法直接封装在新变量中:
obj1= {...obj2}

您也可以使用此克隆库来深度克隆对象。

 npm install --save clone
const clone = require('clone');

const clonedObject = clone(sourceObject);

您可以原型化对象,然后在每次要使用和更改对象时调用对象实例:

function object () {
  this.x = 5;
  this.y = 5;
}
var obj1 = new object();
var obj2 = new object();
obj2.x = 6;
console.log(obj1.x); //logs 5

您还可以将参数传递给对象构造函数

function object (x, y) {
   this.x = x;
   this.y = y;
}
var obj1 = new object(5, 5);
var obj2 = new object(6, 6);
console.log(obj1.x); //logs 5
console.log(obj2.x); //logs 6

希望这会有所帮助。

本文地址:http://javascript.askforanswer.com/zainode-jszhongkelongduixiang.html
文章标签: ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!