javascript with Nodejs: как клонировать объект



object assign deep (9)

Если я клонирую массив, я использую cloneArr = arr.slice()

Я хочу знать, как клонировать объект в nodejs.



Answer #2

Не существует встроенного метода клонирования объектов. Подчеркивание реализует _.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;
};

Extend просто выполняет итерации по всем элементам и создает новый объект с элементами в нем.

Вы можете использовать свою наивную реализацию, если хотите

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

Есть веские причины, чтобы избежать глубокого клонирования, потому что закрытие не может быть клонировано.

Я лично задал вопрос о deep cloning objects before и я пришел к выводу, что вы просто этого не делаете.

Моя рекомендация - использование underscore а метод _.clone для мелких клонов


Answer #3

Вы также можете использовать lodash . Он имеет методы clone и cloneDeep .

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]);

Answer #4

Я внедрил полную глубокую копию. Я считаю, что это лучший выбор для универсального метода клонирования, но он не обрабатывает циклические ссылки.

Пример использования:

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

С этой копией я не могу найти разницы между оригиналом и скопированным, если только оригинал не использовал закрытие при его создании, поэтому я считаю его хорошей реализацией.

Я надеюсь, что это помогает


Answer #5

Для утилит и классов, где нет необходимости сжимать каждую каплю производительности, я часто обманываю и просто использую JSON для выполнения глубокой копии:

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

Это не единственный ответ или самый изящный ответ; все остальные ответы должны рассматриваться для узких мест производства. Однако это быстрое и грязное решение, достаточно эффективное и полезное в большинстве ситуаций, где я бы клонировал простой хэш свойств.


Answer #6

Старый вопрос, но есть более элегантный ответ, чем то, что было предложено до сих пор; используйте встроенный 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.

Надеюсь, это поможет кому-то другому; ссылки на объекты ссылаются на страдания, и это решает каждый раз!


Answer #7

Есть некоторые модули узла, если вы не хотите «сворачивать свои собственные». Этот выглядит хорошо: https://www.npmjs.com/package/clone

Похоже, он обрабатывает всевозможные вещи, включая круговые ссылки. На странице github.com/pvorb/node-clone :

клонирование мастеров клонирования объектов, массивов, объектов Date и объектов RegEx. Все клонируется рекурсивно, так что вы можете клонировать даты в массивах в объектах, например. [...] Циркулярные ссылки? Ага!


Answer #8

Для мелкой копии мне нравится использовать шаблон сокращения (обычно в модуле или такой), например:

var newObject = Object.keys(original).reduce(function (obj, item) {
    obj[item] = original[item];
    return obj;
},{});

Вот jsperf для пары опций: http://jsperf.com/shallow-copying


Answer #9

В зависимости от того, что вы хотите сделать с клонированным объектом, вы можете использовать механизм прототипного наследования javascript и достичь клонированного объекта через:

var clonedObject = Object.create(originalObject);

Просто помните, что это не полный клон - к лучшему или к худшему.

Хорошая вещь в том, что вы на самом деле не дублировали объект, поэтому объем памяти будет низким.

Некоторые сложные вещи, которые следует помнить об этом методе, это то, что итерация свойств, определенных в цепочке прототипов, иногда немного отличается и тот факт, что любые изменения исходного объекта будут влиять и на клонированный объект, если это свойство не было установлено и на себе ,





node.js