Birden çok JavaScript nesnesinden özellikler nasıl birleştirilir


105

Birden çok JavaScript nesnesini (ilişkilendirilebilir diziler) "eklemenin" en iyi yolunu arıyorum.

Örneğin, verilen:

a = { "one" : 1, "two" : 2 };
b = { "three" : 3 };
c = { "four" : 4, "five" : 5 };

hesaplamanın en iyi yolu nedir:

{ "one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 }

3
Anlamsal bir not: [] sözdizimine rağmen, bunlar dizi değildir. Sipariş gerçekten garanti edilmiyor.
Álvaro González

1
Ecma standartlarına göre yineleme sırası garanti edilmez. Ancak çoğu tarayıcıda uygulanma şeklidir. (John Resig'den) Bu davranış, ECMAScript spesifikasyonu tarafından açıkça tanımsız bırakılmıştır. ECMA-262, bölüm 12.6.4: Özelliklerin numaralandırılmasının mekaniği ... uygulamaya bağlıdır. Bununla birlikte, şartname uygulamadan oldukça farklıdır. ECMAScript'in tüm modern uygulamaları, tanımlandıkları sıraya göre nesne özellikleri aracılığıyla yinelenir. Bu nedenle, Chrome ekibi bunu bir hata olarak kabul etti ve düzeltecek.
Juan Mendes

Yanıtlar:


159

ECMAscript 6, Object.assign()bunu yerel olarak Javascript'te gerçekleştirmek için tanıtıldı .

Object.assign () yöntemi, bir hedef nesne, bir ya da daha fazla kaynak nesnelerden her numaralandırılabilir kendi özelliklerinin değerlerini kopyalamak için kullanılır. Hedef nesneyi döndürür.

Object.assign () üzerindeki MDN belgeleri

var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };

var obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }

Object.assignbirçok modern tarayıcıda destekleniyor, ancak henüz hepsi değil. Böyle bir transpiler kullanın Babel ve traceur geriye doğru uyumlu ES5 JavaScript üretilmesi.


4
Bu söyleyebileceğim en iyilerden biri. E6 artık çoğunlukla kullanıldığından, Object.assign en iyi yanıttır.
Vimalraj Selvam

6
Kaç tane nesnenin birleştirilmesi gerektiğini bilmiyorsanız, bir dizide olduklarından şu şekilde birleştirebilirsiniz:Object.assign.apply({}, [{a: 1}, {b: 2}, ....])
Jeanluca Scaljeri

1
Kullanarak alternatif Object.assign.applynesnelerinin bir dizi birleştirme yerine yayılmış operatörü kullanmaktır:Object.assign( ...objects )
Spen

Bu soruya zaten bir cevap olarak dahil edilen @Spen. Burada çoğaltmanın bir yararı görmedim.
filoxo

4 saat sonra, bu cevap sorunumu Angular 7'de çözdü. Cevabın basitliği ve doğruluğu için teşekkürler.
Gel

35

Jquery'leri şu şekilde kullanabilirsiniz $.extend:

let a = { "one" : 1, "two" : 2 },
    b = { "three" : 3 },
    c = { "four" : 4, "five" : 5 };

let d = $.extend({}, a, b, c)

console.log(d)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


+1 jQuery'nin yöntemini kullanmasanız bile, kendi (belki daha spesifik) uygulamanızı oluşturmanıza yardımcı olması için onların kodunu kullanabilirsiniz.
tvanfosson

25
@Randal: jQuery'yi kullanmamak için birçok mükemmel neden var.
Tim Down

3
Düzenleme:d = $.extend({},a,b,c);
Bob Stein

34

Bunu yapmalı:

function collect() {
  var ret = {};
  var len = arguments.length;
  for (var i = 0; i < len; i++) {
    for (p in arguments[i]) {
      if (arguments[i].hasOwnProperty(p)) {
        ret[p] = arguments[i][p];
      }
    }
  }
  return ret;
}

let a = { "one" : 1, "two" : 2 };
let b = { "three" : 3 };
let c = { "four" : 4, "five" : 5 };

let d = collect(a, b, c);
console.log(d);

Çıktı:

{
  "one": 1,
  "two": 2,
  "three": 3,
  "four": 4,
  "five": 5
}

lengthHer çağrıda dizinin boyutunu aramıyor mu ? Yazmaya for (var i = 0, len = array.length; i < len; ++i)o kadar alışkınım ki , bunu neden yapmaya başladığımı aklımdan bile geçiremiyorum.
tvanfosson

1
Evet doğru. Uzunluğu bir kez önbelleğe almak daha iyi performans sağlar. Ancak, "dizi" bağımsız değişkenlerinin boyutu muhtemelen çok büyük olmadığından, bu durumda gerçekten önemli olmayacaktır.
jhurshman

1
Hayır, biraz IE6 dışında. Uzunluk özelliğine erişimin maliyeti, len değişkenine erişimle aynıdır.
Alsciende

1
@Juan Hatalı olduğuna inanıyorum ve kararımı vermek için bazı testler yaptım. Uzunluğu önbelleğe almak, yıllardır kullanılmayan kolay bir optimizasyon efsanesidir ve kodu (biraz) daha az okunabilir hale getirir. Aslında, uzunluğu önbelleğe almak bazen tarayıcıyı (Safari) yavaşlatır.
Alsciende

2
'For (p in ...' yerine 'for (var p in ...' yazmak daha iyi olmaz mıydı?
Hugo

24

ECMAScript 6, yayılma sözdizimine sahiptir . Ve şimdi bunu yapabilirsiniz:

const obj1 = { 1: 11, 2: 22 };
const obj2 = { 3: 33, 4: 44 };
const obj3 = { ...obj1, ...obj2 };

console.log(obj3); // {1: 11, 2: 22, 3: 33, 4: 44}


12

Alt Çizginin bunu yapmak için birkaç yöntemi vardır;

1. _.extend (hedef, * kaynaklar)

İçinde özelliklerin tümünü kopyala kaynağına yanına nesneleri hedef nesne ve iade hedef nesne.

_.extend(a, _.extend(b, c));
=> {"one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 }

Veya

_.extend(a, b);
=> {"one" : 1, "two" : 2, "three" : 3}
_.extend(a, c);
=> {"one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 }

2. _.defaults (nesne, * varsayılanlar)

Doldurun tanımlanmamış özellikler nesne değerlerle varsayılan nesne ve dönüş nesnesi .

_.defaults(a, _.defaults(b, c));
=> {"one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 }

Veya

_.defaults(a, b);
=> {"one" : 1, "two" : 2, "three" : 3}
_.defaults(a, c);
=> {"one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 }

4

İşlev neden 3 bağımsız değişkenle sınırlandırılsın? Ayrıca, kontrol edin hasOwnProperty.

function Collect() {
    var o={};
    for(var i=0;i<arguments.length;i++) {
      var arg=arguments[i];
      if(typeof arg != "object") continue;
      for(var p in arg) {
        if(arg.hasOwnProperty(p)) o[p] = arg[p];
      }
    }
    return o;
}

4

Yüzeysel klonlama (prototip hariç) veya nesnelerin birleştirilmesi artık Object.assign () ' den daha kısa bir sözdizimi kullanılarak mümkündür .

Nesne değişmezleri için yayılma sözdizimi ECMAScript 2018'de tanıtıldı):

const a = { "one": 1, "two": 2 };
const b = { "three": 3 };
const c = { "four": 4, "five": 5 };

const result = {...a, ...b, ...c};
// Object { "one": 1, "two": 2 , "three": 3, "four": 4, "five": 5 }

Yayılma (...) operatörü birçok modern tarayıcıda desteklenmektedir ancak hepsinde .

Bu yüzden Babel gibi bir aktarıcı kullanmanız tavsiye edilir. ECMAScript 2015+ kodunu mevcut ve daha eski tarayıcılarda veya ortamlarda geriye dönük olarak uyumlu bir JavaScript sürümüne dönüştürmek için .

Bu, Babel'in sizin için oluşturacağı eşdeğer koddur :

"use strict";

var _extends = Object.assign || function(target) {
  for (var i = 1; i < arguments.length; i++) {
    var source = arguments[i];
    for (var key in source) {
      if (Object.prototype.hasOwnProperty.call(source, key)) {
        target[key] = source[key];
      }
    }
  }
  return target;
};

var a = { "one": 1, "two": 2 };
var b = { "three": 3 };
var c = { "four": 4, "five": 5 };

var result = _extends({}, a, b, c);
// Object { "one": 1, "two": 2 , "three": 3, "four": 4, "five": 5 }

Bu, kabul edilen cevaptan çok daha sağlam bir cevaptır. Teşekkürler!
Kaleb Anderson

3
function Collect(a, b, c) {
    for (property in b)
        a[property] = b[property];

    for (property in c)
        a[property] = c[property];

    return a;
}

Uyarı: Önceki nesnelerdeki mevcut özelliklerin üzerine yazılacaktır.


2
Bu, sonunda yan etkiye sahiptir a === d. Bu iyi olabilir ve olmayabilir.
tvanfosson

3

Bir nesne için ES7 yayılma operatörünü kullanmak kolaydır , tarayıcı konsolunuza

({ name: "Alex", ...(true  ? { age: 19 } : { })}) // {name: "Alex", age: 19}
({ name: "Alex", ...(false ? { age: 19 } : { })}) // {name: "Alex",        }

1
Güzel. Bu soru 10 yıldan daha eski, bu kadar basit bir işlemin şimdi kolay olmasına sevindim. Başkalarının cevaplarına bakarsanız daha önce o kadar kolay değildi.
Vlad

bu yüzden kendi cevabımı bıraktım :)
Purkhalo Alex

2

Dinamik sayıda nesneyi birleştirmek için Object.assign, yayılma sözdizimi ile kullanabiliriz .

const mergeObjs = (...objs) => Object.assign({}, ...objs);

Yukarıdaki işlev, herhangi bir sayıda nesneyi kabul eder ve tüm özelliklerini, önceki nesnelerin üzerine yazarak sonraki nesnelerin özelliklerine sahip yeni bir nesnede birleştirir.

Demo:

Bir dizi nesneyi birleştirmek için benzer bir yöntem uygulanabilir.

const mergeArrayOfObjs = arr => Object.assign({}, ...arr);

Demo:


1

Muhtemelen, en hızlı, verimli ve daha genel yol şudur (istediğiniz sayıda nesneyi birleştirebilir ve hatta ilkine kopyalayabilirsiniz -> atama):

function object_merge(){
    for (var i=1; i<arguments.length; i++)
       for (var a in arguments[i])
         arguments[0][a] = arguments[i][a];
   return arguments[0];
}

Ayrıca, ilk nesneyi referansla geçerken değiştirmenize olanak tanır. Bunu istemiyor ancak tüm özellikleri içeren tamamen yeni bir nesneye sahip olmak istiyorsanız, ilk argüman olarak {} 'ı iletebilirsiniz.

var object1={a:1,b:2};
var object2={c:3,d:4};
var object3={d:5,e:6};
var combined_object=object_merge(object1,object2,object3); 

kombine_nesne ve nesne1, nesne1, nesne2, nesne3 özelliklerini içerir.

var object1={a:1,b:2};
var object2={c:3,d:4};
var object3={d:5,e:6};
var combined_object=object_merge({},object1,object2,object3); 

Bu durumda, birleşik_nesne, nesne1, nesne2, nesne3 özelliklerini içerir ancak nesne1 değiştirilmez.

Burayı kontrol edin: https://jsfiddle.net/ppwovxey/1/

Not: JavaScript nesneleri referans olarak aktarılır.


1

ES6 ++

Soru, çeşitli farklı nesneleri bir tanesine eklemektir .

let obj = {};
const obj1 = { foo: 'bar' };
const obj2 = { bar: 'foo' };
Object.assign(obj, obj1, obj2);
//output => {foo: 'bar', bar: 'foo'};

nesneler olan birden çok anahtarı olan bir nesneniz olduğunu varsayalım:

let obj = {
  foo: { bar: 'foo' },
  bar: { foo: 'bar' }
}

bulduğum çözüm buydu (hala foreach yapmam gerekiyor: /)

let objAll = {};

Object.values(obj).forEach(o => {
  objAll = {...objAll, ...o};
});

Bunu yaparak, TÜM nesne anahtarlarını bire dinamik olarak ekleyebiliriz.

// Output => { bar: 'foo', foo: 'bar' }

0

En basit: yayma operatörleri

var obj1 = {a: 1}
var obj2 = {b: 2}
var concat = { ...obj1, ...obj2 } // { a: 1, b: 2 }

-2
function collect(a, b, c){
    var d = {};

    for(p in a){
        d[p] = a[p];
    }
    for(p in b){
        d[p] = b[p];
    }
    for(p in c){
        d[p] = c[p];
    }

    return d;
}
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.