How do you clone an array of objects using underscore?
1 2 3 4 5 6 | #!/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)); |
这将导致:
1 | [{"f":1},{"f":55},{"f":10}] |
克隆似乎不起作用!所以我从RTFM中看到:
http://underlinejs.org/克隆
Create a shallow-copied clone of the object. Any nested objects or arrays will be copied by reference, not duplicated.
所以
好吧,有一个诀窍!如果克隆不"克隆"嵌套对象,则可以通过在一个映射调用中显式克隆每个对象来强制克隆它!这样地:
1 2 3 4 5 6 | #!/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)); |
印刷品:
1 | [{"f":1},{"f":5},{"f":10}] |
哎呀!
从Github上的问题中提取的另一个解决方案可以处理任何级别的嵌套数据,不需要下划线:
1 | JSON.parse(JSON.stringify(obj)) |
fwiw,lodash具有克隆edeep功能:
This method is like _.clone except that it recursively clones value.
下划线API引用:
_.toArray(list) Creates a real Array from the list (anything
that can be iterated over). Useful for transmuting the arguments
object.
…或者在本例中,克隆一个数组。试试这个:
1 2 3 4 5 | 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(或者如果需要使用1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | 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 */ |