#!/usr/bin/env node
var _ = require('underscore');
var a = [{f: 1}, {f:5}, {f:10}];
var b = _.clone(a);
b[1].f = 55;
console.log(JSON.stringify(a));
Это приводит к:
[{"f":1},{"f":55},{"f":10}]
Клон не работает! Итак, я RTFM, и вижу это:
http://underscorejs.org/#clone
Создайте мелко скопированный клон объекта. Любые вложенные объекты или массивы будут скопированы по ссылке, а не дублированы.
Так что _.clone
это довольно бесполезно. Есть ли способ скопировать массив объектов?
javascript
underscore.js
Джесс
источник
источник
Ответы:
Что ж, уловка есть! Если clone не «клонирует» вложенные объекты, вы можете принудительно клонировать каждый объект внутри вызова карты! Как это:
#!/usr/bin/env node var _ = require('underscore'); var a = [{f: 1}, {f:5}, {f:10}]; var b = _.map(a, _.clone); // <---- b[1].f = 55; console.log(JSON.stringify(a));
Печать:
[{"f":1},{"f":5},{"f":10}]
Ура!
a
без изменений! Теперь я могу редактироватьb
по своему вкусу!источник
Другое решение, извлеченное из проблемы на Github, которое работает с любым уровнем вложенных данных и не требует подчеркивания:
JSON.parse(JSON.stringify(obj))
источник
JSON.stringify
возникает ошибка. Что не так в оригинале, но все же интересное положение вещей.a = {simple: 'thing'}; a.cycle = a ; JSON.stringify(a)
.Date
илиRegex
экземпляры, они будут сериализованы в строки. Не конец света, но вам нужно справиться с этим, если вы используете это и ожидаетеDate
экземпляров.undefined
это, вы захотите,JSON.parse(JSON.stringify(obj) || null)
иначе это выдаст ошибку.function
s.FWIW, lodash имеет функцию cloneDeep :
источник
Справочник по API Underscore :
... или, в данном случае, клонирование массива. Попробуй это:
var _ = require('underscore'); var array1 = [{a:{b:{c:1}}},{b:{c:{a:2}}},{c:{a:{b:3}}}]; var array2 = _.toArray(array1); console.log(array1 === array2); --> false console.log(array1[0] === array2[0]); --> true
Следующее - приложение, которое я создал после комментария Стива ниже -thx
Ванильный JS (или использующий,
_.clone
если нужно) рекурсивный помощник для глубокого клонирования :function clone(thing, opts) { var newObject = {}; if (thing instanceof Array) { return thing.map(function (i) { return clone(i, opts); }); } else if (thing instanceof Date) { return new Date(thing); } else if (thing instanceof RegExp) { return new RegExp(thing); } else if (thing instanceof Function) { return opts && opts.newFns ? new Function('return ' + thing.toString())() : thing; } else if (thing instanceof Object) { Object.keys(thing).forEach(function (key) { newObject[key] = clone(thing[key], opts); }); return newObject; } else if ([ undefined, null ].indexOf(thing) > -1) { return thing; } else { if (thing.constructor.name === 'Symbol') { return Symbol(thing.toString() .replace(/^Symbol\(/, '') .slice(0, -1)); } // return _.clone(thing); // If you must use _ ;) return thing.__proto__.constructor(thing); } } var a = { a: undefined, b: null, c: 'a', d: 0, e: Symbol('a'), f: {}, g: { a:1 }, h: [], i: [ { a:2 }, { a:3 } ], j: [ 1, 2 ], k: function (a) { return a; }, l: /[a-z]/g, z: [ { a: undefined, b: null, c: 'b', d: 1, e: Symbol(1), f: {}, g: { b:2 }, h: { c:{ c:3 } }, i: { a:Symbol('b') }, j: { a:undefined, b:null }, k: [], l: [ 1, [ 1, 2 ], [ [ 1, 2, 3 ] ] ], m: function (a) { return !a; }, n: { a:function (a) { return !!a; } }, o: /(a|b)/i } ] }; var b = clone(a); var c = clone(a, { newFns:true }); /* Results - value beneath each for reference: a.a === b.a --> true undefined a.b === b.b --> true null a.c === b.c --> true 'a' a.d === b.d --> true 0 a.e === b.e --> false Symbol(a) a.f === b.f --> false {} a.g === b.g --> false { a:1 } a.h === b.h --> false [] a.i === b.i --> false [ { a:2 }, { a:3 } ] a.i[0] === b.i[0] --> false { a:2 } a.i[0].a === b.i[0].a --> true 2 a.j === b.j --> false [ 1, 2 ] a.k === b.k --> true a.k === c.k --> false function (a) { return a; } a.l === b.l --> false /[a-z]/g a.z === b.z --> false [Object] a.z[0].a === b.z[0].a --> true undefined a.z[0].b === b.z[0].b --> true null a.z[0].c === b.z[0].c --> true 'b' a.z[0].d === b.z[0].d --> true 1 a.z[0].e === b.z[0].e --> false Symbol(1) a.z[0].f === b.z[0].f --> false {} a.z[0].g === b.z[0].g -- > false { b:2 } a.z[0].g.b === b.z[0].g.b --> true 2 a.z[0].h === b.z[0].h --> false { c:{ c:3 } } a.z[0].h.c === b.z[0].h.c --> false { c:3 } a.z[0].h.c.c === b.z[0].h.c.c --> true 3 a.z[0].i === b.z[0].i --> false { a:Symbol(b) } a.z[0].i.a === b.z[0].i.a --> false Symbol(b) a.z[0].j === b.z[0].j --> false { a:undefined, b:null } a.z[0].j.a === b.z[0].j.a --> true undefined a.z[0].k === b.z[0].k --> false [] a.z[0].l === b.z[0].l --> false [ 1, [ 1, 2 ], [ [ 1, 2, 3 ] ] ] a.z[0].l[1] === b.z[0].l[1] --> false [ 1, 2 ] a.z[0].l[1][1] === b.z[0].l[1][1] --> true 2 a.z[0].m === b.z[0].m --> true a.z[0].m === c.z[0].m --> false function (a) { return !a; } a.z[0].n === b.z[0].n --> false { a:function (a) { return !!a; } } a.z[0].n.a === b.z[0].n.a --> true a.z[0].n.a === c.z[0].n.a --> false function (a) { return !!a; } a.z[0].o === b.z[0].o --> false /(a|b)/i */
источник
_.toArray(list)
не клонирует объекты в массиве.var array1 = [{a: 1}, {a: 2}, {a: 3}];
var array2 = _.toArray(array1);
array2[0].a = 999;
console.log(array1[0]); --> {a: 999}
_.clone
вelse
условии;)