Если я клонирую массив, я использую cloneArr = arr.slice()
Я хочу знать, как клонировать объект в nodejs.
javascript
node.js
гуйлинь 桂林
источник
источник
newObj = obj.clone(args...);
Object.assign не упоминался ни в одном из ответов выше.
let cloned = Object.assign({}, source);
Если вы используете ES6, вы можете использовать оператор распространения:
let cloned = { ... source };
Ссылка: https://developer.mozilla.org/en-US/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 :
источник
Трудно выполнить обычную, но полезную операцию клонирования, потому что то, что следует клонировать рекурсивно, а что просто копировать, зависит от того, как должен работать конкретный объект.
Что-то, что может быть полезно,
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')
Не существует собственного метода клонирования объектов. Underscore
_.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
метод для мелких клонов.источник
Для мелкой копии я предпочитаю использовать шаблон уменьшения (обычно в модуле или подобном), например:
var newObject = Object.keys(original).reduce(function (obj, item) { obj[item] = original[item]; return obj; },{});
Вот jsperf для пары вариантов: http://jsperf.com/shallow-copying
источник
Старый вопрос, но есть более элегантный ответ, чем то, что предлагалось до сих пор; используйте встроенный 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.
Надеюсь, это поможет кому-то другому; перезапись объектных ссылок - это несчастье, и это каждый раз решает его!
источник
Вы также можете использовать 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]);
источник
В зависимости от того, что вы хотите сделать со своим клонированным объектом, вы можете использовать прототипный механизм наследования 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; }
С этой копией я не могу найти никакой разницы между оригиналом и копией, кроме случаев, когда оригинал использовал замыкания при его построении, поэтому я думаю, что это хорошая реализация.
Я надеюсь, что это помогает
источник
для массива можно использовать
var arr = [1,2,3]; var arr_2 = arr ; print ( arr_2 );
arr = arr.slice (0);
print ( arr ); arr[1]=9999; print ( arr_2 );
источник
Объекты и массивы в JavaScript используют вызов по ссылке, если вы обновите скопированное значение, оно может отразиться на исходном объекте. Чтобы предотвратить это, вы можете глубоко клонировать объект, чтобы предотвратить передачу ссылки, используя команду запуска метода cloneDeep библиотеки lodash
const ld = require('lodash') const objectToCopy = {name: "john", age: 24} const clonedObject = ld.cloneDeep(objectToCopy)
источник