アレイのクローンを作成する場合は、 cloneArr = arr.slice()
nodejsでオブジェクトを複製する方法を知りたいです。
回答:
パフォーマンスのすべての低下を絞る必要がないユーティリティとクラスの場合、私はよくチートし、JSONを使用してディープコピーを実行します。
function clone(a) {
return JSON.parse(JSON.stringify(a));
}
これが唯一の答えや最もエレガントな答えではありません。他のすべての回答は、本番のボトルネックについて検討する必要があります。ただし、これは迅速かつダーティなソリューションであり、非常に効果的で、プロパティの単純なハッシュを複製するほとんどの状況で役立ちます。
newObj = obj.clone(args...);
Object.assignは、上記の回答のいずれにも記載されていません。
let cloned = Object.assign({}, source);
ES6を使用している場合は、spread演算子を使用できます。
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ページから:
clone mastersは、オブジェクト、配列、日付オブジェクト、およびRegExオブジェクトを複製します。すべてが再帰的に複製されるため、たとえば、オブジェクトの配列に日付を複製できます。[...]循環参照?うん!
再帰的に複製するものとコピーするだけのものは特定のオブジェクトがどのように機能するかに依存しているため、一般的ですが有用な複製操作を行うのは困難です。
役に立つかもしれないものは
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')
オブジェクトのクローンを作成するネイティブメソッドはありません。アンダースコア_.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は浅いクローンのための方法です
浅いコピーの場合は、次のように(通常はモジュールなどで)reduceパターンを使用します。
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 } }
空のオブジェクト{}での最初のパラメーターの使用に注意してください-これは、コピーされたオブジェクトを新しいオブジェクトにコピーする必要があることを拡張に伝えます。既存のオブジェクトを最初のパラメーターとして使用する場合、2番目(およびそれ以降)のパラメーターは、最初のパラメーター変数にディープマージコピーされます。
上記のサンプル変数を使用して、これを行うこともできます。
var anotherMergeVar = { foo: "bar" };
extend(copiedObject, { anotherParam: 'value' }, anotherMergeVar);
console.log(copiedObject);
// outputs:
// { test: 12345, nested: { val: 6789 }, anotherParam: 'value', foo: 'bar' }
非常に便利なユーティリティです。特に、AngularJSとjQueryでの拡張に慣れている場合は特に便利です。
これが他の誰かを助けることを願っています。オブジェクト参照の上書きは悲惨であり、これは毎回それを解決します!
クローンオブジェクトをどのように処理するかに応じて、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;
}
このコピーでは、元の構造とコピーされたものの違いを見つけることができません。ただし、元の構造でクロージャーが使用されている場合を除きます。そのため、適切な実装だと思います。
それが役に立てば幸い
JavaScriptのオブジェクトと配列は参照渡しを使用します。コピーされた値を更新すると、元のオブジェクトに反映される可能性があります。これを防ぐには、lodashライブラリのcloneDeepメソッドのrunコマンドを使用して、オブジェクトをディープクローンし、参照が渡されないようにします。
npmインストールlodash
const ld = require('lodash')
const objectToCopy = {name: "john", age: 24}
const clonedObject = ld.cloneDeep(objectToCopy)