別のオブジェクトでオブジェクトのプロパティを複製する方法は?


185

オブジェクトを考える:

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

次のように別のオブジェクトsecondObject内にプロパティをコピーするにはどうすればよいですか

var secondObject = {
    key1 : 'value1',
    key2 : 'value2',
    key3 : 'value3',
    key4 : 'value4'
};

への参照を使用してfirstObject?このようなもの:

var secondObject = {
    firstObject,
    key3 : 'value3',
    key4 : 'value4'
};

(これは機能しません...コードをどのように構成するかを大きな行で示すためだけに置いています)。

JavaScriptフレームワーク使用せずに解決策はありますか?



1
問題は、浅いコピーと深いコピーのどちらが必要かということです。深い場合、どのくらい深いですか?
georg

5
FWIW、それらは「属性」ではなく「プロパティ」と呼ばれます。
TJクラウダー

それにもかかわらず動作します本当に醜いここでの何か(実際にはお勧めできませんジャストワンライナー、概念実証!):secondObject = JSON.parse('{' + JSON.stringify(firstObject).match(/^.(.*).$/)[1] + ',' + JSON.stringify(secondObject).match(/^.(.*).$/)[1] + '}');
ベン・リー

@TJCrowder:私は質問を修正しました...ありがとう。
Igor Popov

回答:


213
for(var k in firstObject) secondObject[k]=firstObject[k];

3
@BenLee、あなたがここで欠けているのは、イゴールが彼が持っている正確な使用法を示しているということですhasOwnProperty。私はあなたのポインタが有用見つけるが、私は適用の考え方を検討任意のにルールを任意の有害な愚かな状況を。進行中のこれらすべてのパターン駆動型開発プラクティスと同様に、それを個人的なものにしないでください...
Michael Krelin-ハッカー

1
@ MichaelKrelin-hacker、ここで欠けているのは、StackOverflowがOPのためだけではないということです。これは、ポインタが役立つ可能性のある、わずかに異なるユースケースを持つ将来の訪問者の参照として使用されます。
Ben Lee

@BenLee、私はIgorPopovではありません;-)そして、OPではないので、ポインタは有用であると私はすでに言っています。
マイケルクレリン-ハッカー、2012年

23
あなたはhasOwnProperty()テストを省略し、物事はちょっと働き続けます。時間が経つにつれてオブジェクトがより複雑になったため、停止するまで。それ以外は、あまりにも多くのものがコピーされたため、コードの無関係な部分で不思議に壊れます。また、デバッグのコンテキストもありません。JSはそのような問題を抱えているため、このような問題が発生しないように注意深くコーディングすることが賢明です。
Eli Bendersky 2013

2
私はこの答えは次のリンクごとに更新する必要があると思いますdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/... {:1、B:2} = constのターゲット。const source = {b:4、c:5}; const returnedTarget = Object.assign(target、source); console.log(target); //予想される出力:Object {a:1、b:4、c:5} console.log(returnedTarget); //予想される出力:Object {a:1、b:4、c:5}
Elbassel

170

ここで@Bardzuśnyの答えからヒントを得て、ES6はネイティブソリューション、つまりObject.assign()関数を提供しました!

使い方は簡単です:

Object.assign(secondObject, firstObject);

それでおしまい!

現在のサポートは明らかに貧弱です。これは、Firefox(34+)でのみサポートされていますが、Chrome(45+)およびOpera(32+)では、「実験的フラグ」を設定する必要があります。

Chrome、Firefox、Opera、Safari、Edgeの最新バージョンでサポートされるようになり、サポートが向上しています(IEは特にサポートしていません)。BabelやTraceurなどのトランスパイラーも利用できます。詳細はこちらをご覧ください。


4
+1、もう1つの素晴らしいES6機能。もちろん、ブラウザやNode.JSのサポートも今のところ不足していますが、あなたが言ったように、利用可能なトランスパイラーがあります。そして、それらが気に入らない場合-shimsgithub.com/paulmillr/es6-shim(またはスタンドアロン、Object.assign()shim:github.com/ljharb/object.assignのみ)。
bardzusny

1
@XoyceリンクされたMDNページを確認すると、「ソース値がオブジェクトへの参照の場合、その参照値のみがコピーされます」と明記されています。そのため、実際には参照が保持され、オブジェクトはコピーされません。予期しない動作に対する警告は依然として適切であり、適切な期待を持つことになります。
DIMMリーパー

@mostafizこのページの質問とその他の回答では「firstObject」と「secondObject」という名前を使用しているため、編集内容をロールバックしました。ここでは、明確さと一貫性のために同じ名前を使用しました。
DIMMリーパー2017

これが質問と一致する場合は、問題ありません。
モスタフィズラーマン2017

1
@pdemはい-kingPuppyの回答を参照してください。
DIMMリーパー

101

ES6ごと-スプレッド構文

あなたは単に使うことができます:

const thirdObject = {
   ...firstObject,
   ...secondObject   
}

これにより、これらのオブジェクトを参照渡しする問題が回避されます。

さらに、ネストが深いオブジェクトも処理します。


2
うわー、これは本当に素晴らしいです:)答えをありがとう。明らかに、(それは少し前だったので)私はもうそれを必要としませんが、他の誰かを助けるかもしれません。
イゴールポポフ

1
ES6をさらにクールに使用するための+1!上記のMDNドキュメントでは、オブジェクトでのスプレッドオペレーターの使用について言及していないため、実際の動作を確認するためにフィドルを作成しました:es6fiddle.net/im3ifsg0
DIMM Reaper

1
@jaepage-参考のために良いコメント。単純なプロパティ名を持つオブジェクト(元の質問による)反復可能です。
kingPuppy 2017

1
Chromeで動作します。これはES6です。現在、BabelまたはいくつかのES6トランスパイラーが必要です。今後、すべてのブラウザでこの構文がサポートされる予定です。
kingPuppy

89

次のように、最初のオブジェクトのプロパティをループして、2番目のオブジェクトに割り当てます。

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

var secondObject = {
    key3 : 'value3',
    key4 : 'value4'
};

for (var prop in firstObject) {
    if (firstObject.hasOwnProperty(prop)) {
        secondObject[prop] = firstObject[prop];
    }
}

for- inループでは十分ではありません。あなたが必要hasOwnPropertyです。理由の詳細については、http://bonsaiden.github.com/JavaScript-Garden/#object.forinloopを参照してください。


@RobW、私はOPがreference技術的な意味で使用しているとは思いませんでした。私は彼が自然言語の「言及」を意味するだけだと思います。
ベン・リー

1
@RobW:OPは実際に「コピー」と言っていました。
TJクラウダー2012

49

ES5が私たちをもたらしたので、ここでネクロマンサーをプレイしました。Object.keys()これらすべての.hasOwnProperty()チェックから私たちを救う可能性があります。

Object.keys(firstObject).forEach(function(key) {
  secondObject[key] = firstObject[key];
});

または、それを関数にラップします(lodashの限定された「コピー」_.assign()):

function assign(object, source) {
  Object.keys(source).forEach(function(key) {
    object[key] = source[key];
  });
}

assign(secondObject, firstObject); // assign firstObject properties to secondObject

Object.keys()は比較的新しいメソッドであり、特にIE <9では使用できません。実際には.forEach()、通常のforループの代わりに使用した配列メソッドも同じです。

幸いなことに、これらの古くからあるブラウザーで使用できるes5-shimがあり、ES5の多くの機能(これら2つを含む)をポリフィルします。

(私は、クールで新しい言語機能の使用を控えているのとは対照的に、すべてポリフィルが好きです。)


突然、どこからでも2つの反対投票が行われます。それらの人がこのコメントを読む可能性は低いですが、実際の理由は何ですか?私の答えを変更/改善するためにあなたが提案することはありますか?
bardzusny 2015

1
これは間違いなく一番上に値するだけでなく、オブジェクトスプレッドイニシャライザ(ES6)も同様です。これは、矢印関数でさらにきれいに見えます!
mjohnsonengr 2016年

12

Necro'ingを使用すると、hasOwnPropertyと実際のオブジェクトチェックを使用してディープコピーメソッドを見つけることができます。

var extend = function (original, context, key) {
  for (key in context)
    if (context.hasOwnProperty(key))
      if (Object.prototype.toString.call(context[key]) === '[object Object]')
        original[key] = extend(original[key] || {}, context[key]);
      else
        original[key] = context[key];
  return original;
};

これは配列や関数オブジェクトをディープコピーしないことに注意してください(ただし、他のすべての種類のオブジェクトをディープコピーします)。
Matt Browne 2015年

1
あなたは深いコピー配列にしたい場合うん、あなただけ含まれるように型チェックを修正'[object Array]'
Nijikokun

12

Object.assignを使用してオブジェクトを組み合わせることができます。これは、共通のプロパティを右から左に組み合わせてオーバーライドします。つまり、左の同じプロパティが右でオーバーライドされます。

また、ソースオブジェクトが変更されないように、最初に空のオブジェクトを指定することが重要です。ソースオブジェクトObject.assign()自体は新しいオブジェクトを返すため、ソースオブジェクトはクリーンなままにしておく必要があります。

お役に立てれば!

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

var secondObject = {
    key3 : 'value3',
    key4 : 'value4'
};

var finalObject = Object.assign({}, firstObject, secondObject)

console.log(finalObject)


しかし、最初のオブジェクトを変更したい場合はどうでしょか?オブジェクトAとオブジェクトBがあり、すべてのプロパティがオブジェクトBのプロパティと同じになるようにオブジェクトAを変更したいですか?Object.assign(A、B)を実行しますか?
TKoL 2017

そのMozilla Developer Networkページによると、IE、Android WebView、Android Operaでは残念ながらサポートされていません。
Yetti99

6

kingPuppyアイデアとOPアイデア(浅いコピー)の改善-OPの「例」に3つのドットのみを追加します:)

var secondObject = {
    ...firstObject,
    key3 : 'value3',
    key4 : 'value4'
};


4

これは動作するはずですここでテストします

var secondObject = {
    firstObject: JSON.parse(JSON.stringify(firstObject)),
    key3 : 'value3',
    key4 : 'value4'
};

:これは、firstObject
注2のメソッドをコピーしません。古いブラウザーで使用するには、jsonパーサーが必要です
注3:特にfirstObjectメソッドが含まれている場合、参照による割り当ては実行可能なオプションです。指定されたjsfiddleの例を適宜調整しました


3

残念ながら、そのようなオブジェクトに変数への参照を置くことはできません。ただし、オブジェクトの値を別のオブジェクトにコピーする関数を作成できます。

function extend( obj1, obj2 ) {
    for ( var i in obj2 ) {
        obj1[i] = obj2[i];
    }
    return obj1;
}

var firstObject = {
    key1: "value1",
    key2: "value2"
};

var secondObject = extend({
    key3: "value3",
    key4: "value4"
}, firstObject );

これにより、ネイティブプロパティもコピーされます。そして、オブジェクト自体であるプロパティはどうですか?
KooiInc

1

2番目のオブジェクトに存在するプロパティのみを取得したい場合Object.keysは、最初のオブジェクトのプロパティを取得するために使用できます。2つの方法があります。

A.) map副作用を使用して最初のオブジェクトのプロパティを2番目のオブジェクトに割り当てるには:

var a = {a:100, b:9000, c:300};
var b = {b:-1};

Object.keys(a).map(function(key, index) {
    if (typeof b[key] !== 'undefined') {
        console.log(key);
        b[key] = a[key];    
    }
});

B.)またはreduce、新しいオブジェクトを作成して2番目のオブジェクトに割り当てます。このメソッド、2番目のオブジェクトが最初のオブジェクトと一致しなかったプロパティを置き換えることに注意してください。

var a = {a:100, b:9000, c:300};
var b = {b:-1, d:-1}; // d will be gone

b = Object.keys(a).reduce(function(result, current) {
    if (typeof b[current] !== 'undefined') {
        result[current] = a[current];   
    }
    return result;
}, {});

1

プロパティスプレッド表記を使用します。これはES2018で追加されました(配列/反復可能オブジェクトの分散は以前のES2015でした)、{... firstObject}は列挙可能なすべてのプロパティを離散プロパティとして分散します。

let secondObject = {
      ...firstObject,
      key3 : 'value3',
      key4 : 'value4'
    }

あなたの答えと、なぜそれが目の前の問題を解決しているのかについてコンテキストを教えていただけますか
Tamir Klein

0

firstObjectをsecondObjectのプロトタイプとして使用し、プロパティ記述子を追加します。

var secondObject = Object.create(firstObject, {
      key3: {value: "value3", writable: true, configurable: true, enumerable: true},
      key4: {value: "value4", writable: true, configurable: true, enumerable: true}
      });

それは確かにワンライナーではありませんが、より多くのコントロールを提供します。プロパティ記述子に興味がある場合は、この記事を読むことをお勧めします:http ://patrickdelancy.com/2012/09/property-descriptors-in-javascript/#comment-2062 およびMDNページhttps://developer.mozilla。 org / en-US / docs / Web / JavaScript / Reference / Global_Objects / Object / create

値を割り当てて記述子を省略し、少し短くすることもできます。

var secondObject = Object.create(firstObject, {
      key3: {value: "value3"}
      key4: {value: "value4"}
  });

互換性:ECMAScript 5、IE9 +


0
var firstObject = {
     key1: "value1",
     key2: "value2"
};

var secondObject = {
     key3: "value3",
     key4: "value4"
     copy: function(firstObject){
           this.key1 = firstObject.key1;
           this.key2 = firstObject.key2;
     }
 };

次の方法を使用すると、プロパティがコピーされます

secondObject.copy(firstObject)

私はJavaScriptに非常に慣れていませんが、これは機能していることがわかりました。少し長すぎると思いますが、うまくいきます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.