Başka bir nesnede nesne özellikleri nasıl çoğaltılır?


185

Nesne verildiğinde:

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

nasıl başka bir nesne ( secondObject) içindeki özellikleri kopyalayabilirsiniz :

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

Bir referans kullanarak firstObject? Bunun gibi bir şey:

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

(Bu işe yaramaz ... Ben sadece kodu nasıl yapılandırmak istiyorum büyük satırlarda göstermek için koydu).

Bir çözüm mümkün mü olmadan herhangi JavaScript çerçevelerini kullanarak?



1
Soru şu ki, sığ mı yoksa derin bir kopya mı istiyorsunuz? Derin ise, ne kadar derin?
georg

5
FWIW, bunlara "özellikler" değil "özellikler" denir.
TJ Crowder

İşte yine de gerçekten çirkin bir şey (aslında tavsiye edilmez! Sadece tek katmanlı bir kavram kanıtı):secondObject = JSON.parse('{' + JSON.stringify(firstObject).match(/^.(.*).$/)[1] + ',' + JSON.stringify(secondObject).match(/^.(.*).$/)[1] + '}');
Ben Lee

@TJCrowder: Soruyu düzelttim ... teşekkürler.
Igor Popov

Yanıtlar:


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

3
@BenLee, burada eksik olan şey, Igor'un bunun için tam olarak kullanıldığını gösterdiği, ki hasOwnPropertybu işe yaramaz. İşaretçinizi yararlı bulurken, herhangi bir duruma herhangi bir kuralın zararlı ve akılsızca uygulanması fikrini düşünüyorum .
Devam

1
@ MichaelKrelin-hacker, burada eksik olan şey StackOverflow sadece OP yararına değildir. O işaretçi biraz farklı kullanım durumları olabilir gelecek ziyaretçiler için bir referans olarak kullanılır olabilir yararlı olabilir.
Ben Lee

@BenLee, ben IgorPopov değilim ;-) Ve OP değil, ben zaten işaretçiyi yararlı bulduğumu ve cevabınızı da dedim, sevmediğim "gerçekten kullanmalısınız" kısmı.
Michael Krelin - hacker

23
Bir hasOwnProperty()testi atlarsın ve işler çalışmaya devam eder. Duruncaya kadar, nesneleriniz zamanla daha karmaşık hale geldi. Bunun dışında kodun ilgisiz bir bölümünde gizemli bir şekilde kırılıyor çünkü çok fazla kopyalanmış. Ve hata ayıklama için herhangi bir bağlamınız yok. JS böyle berbat, bu tür sorunların ortaya çıkmasını önlemek için çok dikkatli kodlama ihtiyatlı.
Eli Bendersky

2
Bu cevabın aşağıdaki bağlantıya göre güncellenmesi gerektiğini düşünüyorum. Developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… const target = {a: 1, b: 2}; sabit kaynak = {b: 4, c: 5}; const returnTarget = Object.assign (hedef, kaynak); console.log (hedef); // beklenen çıktı: Object {a: 1, b: 4, c: 5} console.log (returnTarget); // beklenen çıktı: Nesne {a: 1, b: 4, c: 5}
Elbassel

170

@ Bardzuśny'nin cevabından bir ipucu alan ES6, yerel bir çözüm sundu: Object.assign()işlev!

Kullanımı basit:

Object.assign(secondObject, firstObject);

Bu kadar!

Şu anda destek açıkça zayıf; Chrome (45+) ve Opera (32+) 'kutudan çıktığı anda yalnızca Firefox (34+) onu destekliyor,' deneysel bayrağın 'ayarlanmasını gerektiriyor.

Destek, Chrome, Firefox, Opera, Safari ve Edge'in en son sürümleriyle destekleniyor (IE'nin özellikle desteği yok.) Babil ve Traceur gibi transpiller de mevcut. Daha fazla ayrıntı için buraya bakın.


4
+1, başka bir harika ES6 özelliği. Tabii ki tarayıcı / hatta Node.JS desteği şimdilik yok, ancak belirttiğiniz gibi transistörler var. Ve onları sevmiyorsanız - şimler: github.com/paulmillr/es6-shim (veya bağımsız, Object.assign()-sadece şim: github.com/ljharb/object.assign ).
bardzusny

1
@Xoyce Bağlantılı MDN sayfasını kontrol ederseniz, "Kaynak değer bir nesneye başvuru ise, yalnızca bu referans değerini kopyalar." Bu yüzden gerçekten referansı korur ve nesneyi kopyalamaz. Beklenmedik davranışlara karşı uyarınız hala uygun ve uygun beklentilere sahip olmaya geliyor.
DIMM Reaper

@mostafiz Düzenlemenizi geri aldım, çünkü bu sayfadaki soru ve diğer yanıtlar "firstObject" ve "secondObject" adlarını kullanıyor, bu yüzden açıklık ve tutarlılık için burada aynı adları kullandım.
DIMM Reaper

Bu soru ile tutarlıysa sorun değil.
Mostafiz Rahman

1
@pdem Yep - kingPuppy'nin cevabına bakınız .
DIMM Reaper

101

Per ES6 - Spread sözdizimi :

Sadece şunu kullanabilirsiniz:

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

Bu, bu nesneleri referans olarak geçirme problemlerini önler.

Buna ek olarak, derin yuvalama olan nesnelerle ilgilenir.


2
Vay be, bu gerçekten harika :) Cevabınız için teşekkürler. Açıkçası, artık ona ihtiyacım yok (bir süre önce olduğu için), ama başka birine yardımcı olabilir.
Igor Popov

1
Daha serin ES6 kullanımı için +1! Yukarıda değinilen MDN dokümanları, nesnelerde yayılma operatörünün kullanılmasından bahsetmez, bu yüzden eylemde görmek için bir keman yaptım: es6fiddle.net/im3ifsg0
DIMM Reaper

1
@jaepage - referans için iyi bir yorum. Basit özellik isimlerinin bir nesne (asıl soruya başına) olduğu iterable.
kingPuppy

1
Chrome'da çalışıyor, bu ES6, şu anda Babel veya bazı ES6 transpiler'e ihtiyacınız olacak. Gelecekte tüm tarayıcıların bu sözdizimini desteklemesi bekleniyor.
kingPuppy

89

İlk nesnenin özelliklerini gözden geçirin ve ikinci nesneye şu şekilde atayın:

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- indöngü yeterli değildir; ihtiyacınız var hasOwnProperty. Nedeninin ayrıntılı açıklaması için http://bonsaiden.github.com/JavaScript-Garden/#object.forinloop adresine bakın .


@RobW, OP'nin referenceteknik anlamda kullandığını düşünmemiştim . Bence o sadece doğal dil anlamına gelir.
Ben Lee

1
@RobW: OP aslında "kopya" dedi.
TJ Crowder

49

Burada büyücü oynamak, çünkü ES5 Object.keys()bizi tüm bu .hasOwnProperty()kontrollerden kurtarma potansiyeli ile getirdi .

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

Veya, bir işleve sarmak (lodash'ın sınırlı "kopyası" _.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()nispeten yeni bir yöntem, en önemlisi: IE <9 kullanılabilir değil. Aynı aslında .forEach()düzenli fordöngü yerine kullanılan dizi yöntemi için de geçerli .

Neyse ki, bu eski tarayıcılar için birçok ES5 özelliğini (bu ikisi dahil) çoklu dolduracak es5-shim var .

(Tamamen havalı, yeni dil özelliklerini kullanmaktan uzak durmak yerine çoklu dolgular için kullanıyorum.)


Aniden, 2 iniş yok. Bu yorumları okuyacakları için küçük bir şans - onların gerçek nedeni nedir? Cevabımda değişiklik / iyileştirme önerebileceğiniz bir şey var mı?
bardzusny

1
Bu kesinlikle yukarı çıkmayı ve nesne yayma başlatıcıyı daha aşağıya (ES6) yükseltmeyi hak ediyor - bu, ok işlevleriyle daha da temiz görünüyor!
16:27

12

İnsanların hasOwnProperty ve gerçek nesne kontrolü ile derin bir kopyalama yöntemi bulabilmesi için necro'ing:

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;
};

Bunun dizileri veya işlev nesnelerini derin kopyalamadığını (ancak diğer tüm nesne türlerini derin kopyaladığını) unutmayın.
Matt Browne

1
Evet, dizileri derin kopyalamak istiyorsanız, tür denetimini içerecek şekilde değiştirirsiniz'[object Array]'
Nijikokun

12

Nesneleri birleştirmek için Object.assign kullanılabilir . Ortak mülkü sağdan sola birleştirir ve geçersiz kılar, yani soldaki aynı özellik sağ tarafından geçersiz kılınır.

Ve kaynak nesnelerin mutasyona uğramasını önlemek için ilk önce boş bir nesne sağlamak önemlidir . Kaynak nesneler Object.assign()yeni bir nesne döndürdüğü için temiz bırakılmalıdır .

Bu yardımcı olur umarım!

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

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

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

console.log(finalObject)


ama ilk nesneyi değiştirmesini isterseniz ? A nesnesine ve B nesnesine sahipsiniz ve tüm özellikler B nesnesindeki değerlere eşit olacak şekilde A nesnesini değiştirmesini mi istiyorsunuz? Object.assign (A, B) yapar mısınız?
TKoL

Maalesef Mozilla Geliştirici Ağı sayfasına göre IE, Android WebView, Android Opera'da desteklenmiyor.
Yetti99

6

İyileştirilmesi kingPuppy fikri ve OP fikri (sığ kopya) - Sadece OP "Örneğin" için 3 nokta ekleyin :)

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


4

Bu, burada test edilmiş olmalı .

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

Not : bu, firstObject
Not 2'nin yöntemlerini kopyalamaz : eski tarayıcılarda kullanım için bir json ayrıştırıcıya ihtiyacınız olacaktır
Not 3 : referans olarak atama, özellikle firstObjectyöntemler içeriyorsa , uygulanabilir bir seçenektir . Verilen jsfiddle örneğini buna göre ayarlayın


3

Ne yazık ki, böyle bir nesnede bir değişkene başvuru yapamazsınız. Ancak, nesnenin değerlerini başka bir nesneye kopyalayan bir işlev yapabilirsiniz.

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 );

Bu aynı zamanda yerel özellikleri de kopyalar. Ve Nesnelerin kendileri olan özellikler hakkında ne dersiniz?
KooiInc

1

Eğer kapmak istiyorsa sadece ikinci objenin mevcut özelliklerini kullanabileceğiniz Object.keysiki yöntem yapabilirsiniz birinci nesnenin özelliklerini kapmak için:

A.) map yan etkileri kullanarak birinci nesnenin özelliklerini ikinci nesneye atamak için:

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.) veya reduceyeni bir nesne oluşturmak ve ikinci nesneye atamak. Bu yöntemin , ikinci nesnenin, ilk nesneyle eşleşmeyen özellikten önce sahip olabileceği diğer özellikleri değiştirdiğini unutmayın:

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

Özellik yayılım gösterimini kullanın. ES2018'de eklenmiştir (diziler / yinelenebilirler için yayılma daha erkendi, ES2015), {... firstObject} tüm numaralandırılabilir özellikleri ayrık özellikler olarak yayar.

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

lütfen cevabınızla ilgili bir bağlam verebilir misiniz ve soruyu neden elinizde
çözüyor

0

Oldukça firstObject secondObject prototip olarak kullanmak ve özellik tanımlayıcı eklemek:

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

Kesinlikle tek astarlı değil, ama size daha fazla kontrol sağlıyor. Özellik tanımlayıcılarıyla ilgileniyorsanız, bu makaleyi okumanızı öneririz: http://patrickdelancy.com/2012/09/property-descriptors-in-javascript/#comment-2062 ve MDN sayfası https: //developer.mozilla. org / tr-tR / docs / Web / JavaScript / Referans / Global_Objects / Nesne oluşturmak /

Ayrıca sadece değerler atayabilir ve tanımlayıcıları atlayabilir ve biraz daha kısa yapabilirsiniz:

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

Uyumluluk: ECMAScript 5, yani 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;
     }
 };

Follwing yöntemini kullanmak özellikleri kopyalar

secondObject.copy(firstObject)

Javascript için çok yeniyim, ama bu işe yaradı. Biraz fazla sanırım, ama işe yarıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.