Nodejs: how to clone an object

后端 未结 12 2027
情书的邮戳
情书的邮戳 2020-12-04 18:32

If I clone an array, I use cloneArr = arr.slice()

I want to know how to clone an object in nodejs.

相关标签:
12条回答
  • 2020-12-04 19:12

    For utilities and classes where there is no need to squeeze every drop of performance, I often cheat and just use JSON to perform a deep copy:

    function clone(a) {
       return JSON.parse(JSON.stringify(a));
    }
    

    This isn't the only answer or the most elegant answer; all of the other answers should be considered for production bottlenecks. However, this is a quick and dirty solution, quite effective, and useful in most situations where I would clone a simple hash of properties.

    0 讨论(0)
  • 2020-12-04 19:12

    You can use lodash as well. It has a clone and cloneDeep methods.

    var _= require('lodash');
    
    var objects = [{ 'a': 1 }, { 'b': 2 }];
    
    var shallow = _.clone(objects);
    console.log(shallow[0] === objects[0]);
    // => true
    
    var deep = _.cloneDeep(objects);
    console.log(deep[0] === objects[0]);
    
    0 讨论(0)
  • 2020-12-04 19:15

    I implemented a full deep copy. I believe its the best pick for a generic clone method, but it does not handle cyclical references.

    Usage example:

    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
    

    The code itself:

    This code copies objects with their prototypes, it also copy functions (might be useful for someone).

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

    With this copy I can't find any difference between the original and the copied one except if the original used closures on its construction, so i think its a good implementation.

    I hope it helps

    0 讨论(0)
  • 2020-12-04 19:17

    There is no native method for cloning objects. Underscore implements _.clone which is a shallow clone.

    _.clone = function(obj) {
      return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
    };
    

    It either slices it or extends it.

    Here's _.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;
    };
    

    Extend simply iterates through all the items and creates a new object with the items in it.

    You can roll out your own naive implementation if you want

    function clone(o) {
      var ret = {};
      Object.keys(o).forEach(function (val) {
        ret[val] = o[val];
      });
      return ret;
    }
    

    There are good reasons to avoid deep cloning because closures cannot be cloned.

    I've personally asked a question about deep cloning objects before and the conclusion I came to is that you just don't do it.

    My recommendation is use underscore and it's _.clone method for shallow clones

    0 讨论(0)
  • 2020-12-04 19:17

    Old question, but there's a more elegant answer than what's been suggested so far; use the built-in 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 } }
    

    Note the use of the first parameter with an empty object {} - this tells extend that the copied object(s) need to be copied to a new object. If you use an existing object as the first parameter, then the second (and all subsequent) parameters will be deep-merge-copied over the first parameter variable.

    Using the example variables above, you can also do this:

    var anotherMergeVar = { foo: "bar" };
    
    extend(copiedObject, { anotherParam: 'value' }, anotherMergeVar);
    
    console.log(copiedObject);
    
    // outputs:
    // { test: 12345, nested: { val: 6789 }, anotherParam: 'value', foo: 'bar' }
    

    Very handy utility, especially where I'm used to extend in AngularJS and jQuery.

    Hope this helps someone else; object reference overwrites are a misery, and this solves it every time!

    0 讨论(0)
  • 2020-12-04 19:20

    Objects and Arrays in JavaScript use call by reference, if you update copied value it might reflect on the original object. To prevent this you can deep clone the object, to prevent the reference to be passed, using lodash library cloneDeep method run command

    npm install lodash

    const ld = require('lodash')
    const objectToCopy = {name: "john", age: 24}
    const clonedObject = ld.cloneDeep(objectToCopy)
    
    0 讨论(0)
提交回复
热议问题