Cloning an Object in Node.js

后端 未结 21 1841
情书的邮戳
情书的邮戳 2020-11-28 02:03

What is the best way to clone an object in node.js

e.g. I want to avoid the situation where:

var obj1 = {x: 5, y:5};
var obj2 = obj1;
obj2.x = 6;
con         


        
相关标签:
21条回答
  • 2020-11-28 02:32
    var obj2 = JSON.parse(JSON.stringify(obj1));
    
    0 讨论(0)
  • 2020-11-28 02:32

    There is another library lodash, it has clone and cloneDeep.

    clone will clone your object but not create a new instance for non-primitive values, instead it will use the referrence to the original object

    cloneDeep will create literally new objects without having any referrence to the original object, so it more safe when you have to change the object afterwards.

    0 讨论(0)
  • 2020-11-28 02:35

    You can also use this clone library to deep clone objects.

     npm install --save clone
    
    const clone = require('clone');
    
    const clonedObject = clone(sourceObject);
    
    
    0 讨论(0)
  • 2020-11-28 02:36

    There is no built-in way to do a real clone (deep copy) of an object in node.js. There are some tricky edge cases so you should definitely use a library for this. I wrote such a function for my simpleoo library. You can use the deepCopy function without using anything else from the library (which is quite small) if you don't need it. This function supports cloning multiple data types, including arrays, dates, and regular expressions, it supports recursive references, and it also works with objects whose constructor functions have required parameters.

    Here is the code:

    //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;
    };
    
    0 讨论(0)
  • 2020-11-28 02:38

    Simple and the fastest way to clone an Object in NodeJS is to use Object.keys( obj ) method

    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"}
    

    The method Object.keys requires JavaScript 1.8.5; nodeJS v0.4.11 supports this method

    but of course for nested objects need to implement recursive func


    Other solution is to use native JSON (Implemented in JavaScript 1.7), but it's much slower (~10 times slower) than previous one

    var a = {"a": i, "b": i*i};
    var b = JSON.parse(JSON.stringify(a));
    b.a = 0;
    
    0 讨论(0)
  • 2020-11-28 02:39

    None of the answers satisfied me, several don't work or are just shallow clones, answers from @clint-harris and using JSON.parse/stringify are good but quite slow. I found a module that does deep cloning fast: https://github.com/AlexeyKupershtokh/node-v8-clone

    0 讨论(0)
提交回复
热议问题