ES6 + 'da iki javascript nesnesini nasıl birleştirebilirim?


141

Her zaman böyle bir kod yazmak zorunda bıktım bıktınız:

function shallowExtend(obj1,obj2){
  var key;
  for ( key in obj2 ) {
    if ( obj2.hasOwnProperty(key) === false )  continue;
    obj1[key] = obj2[key]
  }
}

Veya kodu kendim yazmak istemiyorsam, bunu zaten yapan bir kitaplık uygulayın. Kesinlikle ES6 + bu kurtarmaya geliyor bize bir Object.prototype.extend(obj2...)veyaObject.extend(obj1,obj2...)

Peki ES6 + böyle bir işlevsellik sağlıyor mu? Henüz orada değilse, böyle bir işlevsellik planlanıyor mu? Planlanmamışsa, neden olmasın?


3
Yani neden bunu eklememiş sizin kütüphaneye?
RobG

12
Bu soruyu @RobG ES6 ilk place.For böyle klişe bok ihtiyaç zorunluluğundan kaldırmak umuduyla ne hakkında olduğunu 's değerinde: github.com/balupton/bal-util/blob/...
balupton

Bir nesneden diğerine isim / değer çiftlerini kopyalamanın genel bir yolu olduğunu düşünmüyorum. Sadece kendi mülklerinizle mi yoksa [[Prototype]]zincirde olanlarla mı ilgileniyorsunuz ? "Derin" veya "sığ" kopyalar yapıyor musunuz? Numaralandırılamayan ve yazılamayan özellikler ne olacak? Sanırım ihtiyacım olanı yapan küçük bir kütüphane fonksiyonuna sahip olmayı tercih ederim ve çoğunlukla yine de önlenebilir.
RobG

Yanıtlar:


206

Object.assign kullanarak ES6'da sığ birleştirme / genişletme / atama yapabileceksiniz:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

Sözdizimi:

Object.assign ( hedef , kaynaklar );

burada ... kaynaklar , kaynak nesneyi / nesneleri temsil eder.

Misal:

var obj1 = {name: 'Daisy', age: 30};
var obj2 = {name: 'Casey'};

Object.assign(obj1, obj2);

console.log(obj1.name === 'Casey' && obj1.age === 30);
// true

64
Küçük bir not: Object.assign hedefi değiştirir. İstediğiniz bu değilse boş bir nesne ile arayabilirsiniz:let merged = Object.assign({}, source1, source2);
david

20
Bunun sığ bir
genişlik

@monzonj, iç içe geçmiş nesneleri, huysuz veya mout kullanmadan genişletme seçeneği yok mu?
Joao Falcao

1
Derin iç içe geçmiş nesneleri sadece bir kütüphane olmadan birleştirmenin iyi bir yolu var Object.assign: cevabımı buradan görebilirsiniz
Ruslan

İç içe nesneleri genişletmenin eski bir yolu kullanıyorJSON.parse(JSON.stringify(src))
Andre Figueiredo

162

Bunun için nesne yayılımı sözdizimini kullanabilirsiniz :

const merged = {...obj1, ...obj2}

Diziler için spread operatörü zaten ES6'nın (ES2015) bir parçasıydı, ancak nesneler için ES9'daki (ES2018) dil spesifikasyonuna eklendi. Bundan önce Babil gibi araçlarda öneri varsayılan olarak etkinleştirildi.


3
Hayır resmi olarak şimdi ES2015 denir: P Ne zamandan beri yıkım ES6'nın bir parçası değil? developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/… Babel- const ob1 = {foo: 123}; const ob2 = {bar: 234}; const merged = {...ob1, ...ob2}; console.log(merged){ foo: 123, bar: 234 }
node'u

9
Bu yıkıcı değil, yayılıyor - ve hayır, nesneler için ES6'nın bir parçası değil. Babilinizdeki deneysel ES7 taslaklarını devre dışı bırakmalısınız.
Bergi

2
Ah affet beni. Haklısın. Şu anda bir babil evre 2 özelliğidir.github.com/sebmarkbage/ecmascript-rest-spread Bunu hiç fark etmedim çünkü babil ile en başından beri kullanıyorum ve varsayılan olarak etkindir. Ama yine de aktarmanız gerektiğinden ve nesne yayılması oldukça basit bir şeydir, yine de tavsiye ederim. Onu seviyorum.
Thijs Koerselman

Gerçekten varsayılan olarak etkinler mi? Kulağa bir böcek gibi geliyor.
Bergi

2
"Aşama 2 veya üstü teklifler varsayılan olarak etkindir". babeljs.io/docs/usage/experimental
Thijs Koerselman

14

Bunun biraz eski bir sorun olduğunu biliyorum, ancak ES2015 / ES6'daki en kolay çözüm Object.assign () kullanarak aslında oldukça basit,

Umarım bu yardımcı olur, DEEP birleşimi de yapar:

/**
 * Simple is object check.
 * @param item
 * @returns {boolean}
 */
export function isObject(item) {
  return (item && typeof item === 'object' && !Array.isArray(item) && item !== null);
}

/**
 * Deep merge two objects.
 * @param target
 * @param source
 */
export function mergeDeep(target, source) {
  if (isObject(target) && isObject(source)) {
    for (const key in source) {
      if (isObject(source[key])) {
        if (!target[key]) Object.assign(target, { [key]: {} });
        mergeDeep(target[key], source[key]);
      } else {
        Object.assign(target, { [key]: source[key] });
      }
    }
  }
  return target;
}

Örnek kullanım:

mergeDeep(this, { a: { b: { c: 123 } } });
// or
const merged = mergeDeep({a: 1}, { b : { c: { d: { e: 12345}}}});  
console.dir(merged); // { a: 1, b: { c: { d: [Object] } } }

7

Eklenmesi Object.mixinşu anda görüşülmekte olan sizin için soruyorsunuz davranışa dikkat çekmek için.https://mail.mozilla.org/pipermail/es-discuss/2012-December/027037.html

Henüz ES6 taslağında olmamasına rağmen, çok fazla destek var gibi görünüyor, bu yüzden yakında taslaklarda görüneceğini düşünüyorum.


13
.mixindüşmüş TC39 tarafından.
Knu

5
Uyarı - bu cevap artık doğru değil, doğru ve çalışan bir yaklaşım için Jack'in cevabına bakın.
Benjamin Gruenbaum

Object.mixin, Object.assign
gotofritz ile

7

ES6

Object.assign(o1,o2) ; 
Object.assign({},o1,o2) ; //safe inheritance
var copy=Object.assign({},o1); // clone o1
//------Transform array of objects to one object---
var subjects_assess=[{maths:92},{phy:75},{sport:99}];
Object.assign(...subjects_assess); // {maths:92,phy:75,sport:99}

ES7 veya Babil

{...o1,...o2} // inheritance
 var copy= {...o1};

1
@FilipBartuzi, bağlandığınız ES6 değil. Ama temelde lodash / alt çizgi içindeki _.extend () 'e eşdeğerdir.
Nostalg.io

5

Belki ES5 Object.definePropertiesyöntemi işi yapacak?

Örneğin

var a = {name:'fred'};
var b = {age: {value: 37, writeable: true}};

Object.defineProperties(a, b);

alert(a.age); // 37

MDN belgeleri: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperties


Yine de dikkatli olun. On en az bir tarayıcıda bu performans sonuçları vardır.
Reuben Morais

1
Bence en ilginç yanı definePropertieskendi özelliklerini tanımlaması. [[prototype]]Zincirdeki özelliklerin üzerine yazmaz , gölgelendirir.
RobG

2
İyi öneri, özelliklerin nasıl davranması gerektiğini tanımlamak için daha fazla olduğu için gerçekten bir kapsam olmamasına rağmen ... Basit bir Object.defineProperties (obj1, obj2) yapmak beklenmedik sonuçlara neden olur.
balupton

Object.getOwnPropertyDescriptorözelliği karmaşık bir değer olduğunda ayarlamak için de kullanmanız gerekir , aksi takdirde referans olarak kopyalarsınız.
dmp
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.