Muszę być w stanie scalić dwa (bardzo proste) obiekty JavaScript w czasie wykonywania. Na przykład chciałbym:
var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }
obj1.merge(obj2);
//obj1 now has three properties: food, car, and animal
Czy ktoś ma do tego skrypt lub wie o wbudowanym sposobie, aby to zrobić? Nie potrzebuję rekurencji i nie muszę scalać funkcji, tylko metody na płaskich obiektach.
javascript
javascript-objects
JC Grubbs
źródło
źródło
var obj2 = { animal: 'dog', food: 'bone' };
, połączenie byłoby{ food: 'bone', car: 'ford', animal: 'dog' }
. Jeśli pracujesz z „zagnieżdżonymi danymi” i chcesz „głębokiego scalenia”, poszukaj odpowiedzi, które wspominają o „głębokim scaleniu” lub „rekurencji”. Jeśli masz wartościarrays
, użyj opcji „arrayMerge” github „TehShrike / deepmerge”, jak wspomniano tutaj .Odpowiedzi:
ECMAScript 2018 Standard Method
Byłoby użyć obiektu rozprzestrzeniania :
merged
jest teraz uniąobj1
iobj2
. Właściwości wobj2
nadpisze te wobj1
.Oto także dokumentacja MDN dla tej składni. Jeśli używasz babel, potrzebujesz wtyczki babel-plugin-transform-object-rest-spread-spread , aby działała.
ECMAScript 2015 (ES6) Standardowa metoda
(patrz MDN JavaScript Reference )
Metoda dla ES5 i wcześniejszych
Zauważ, że to będzie po prostu dodać wszystkie atrybuty
obj2
doobj1
których nie może być to, co chcesz, jeśli nadal chcesz używać niemodyfikowanaobj1
.Jeśli używasz frameworka, który psuje wszystkie prototypy, musisz uzyskać bardziej wyszukane kontrole
hasOwnProperty
, ale ten kod będzie działał w 99% przypadków.Przykładowa funkcja:
źródło
var merged = {...obj1, ...obj2}
.{...obj1, ...{animal: 'dog'}}
jQuery ma również narzędzie do tego: http://api.jquery.com/jQuery.extend/ .
Zaczerpnięte z dokumentacji jQuery:
Powyższy kod spowoduje mutację istniejącego obiektu o nazwie
settings
.Jeśli chcesz utworzyć nowy obiekt bez modyfikowania żadnego z argumentów, użyj tego:
źródło
jQuery.extend(true,settings,override)
, co jest ważne, jeśli właściwość w ustawieniach zawiera obiekt, a zastąpienie ma tylko część tego obiektu. Zamiast usuwać niedopasowane właściwości, głębokie ustawienie zostanie zaktualizowane tylko tam, gdzie istnieje. Wartość domyślna to false.Harmony ECMAScript 2015 (ES6) określa,
Object.assign
który będzie to zrobić.Obecna obsługa przeglądarek jest coraz lepsza , ale jeśli tworzysz przeglądarki, które nie obsługują tej funkcji, możesz skorzystać z funkcji wypełniania .
źródło
Object.assign
ma całkiem przyzwoity zasięg: kangax.github.io/compat-table/es6/…Object.assign({}, obj1, obj2)
Poszukałem kodu, aby scalić właściwości obiektu i znalazłem się tutaj. Ponieważ jednak nie było żadnego kodu do scalania rekurencyjnego, napisałem go sam. (Może rozszerzenie jQuery jest rekurencyjne BTW?) W każdym razie, mam nadzieję, że komuś innemu również się przyda.
(Teraz kod nie używa
Object.prototype
:)Kod
Przykład
Tworzy obiekt o3 jak
źródło
Zauważ, że
underscore.js
'sextend
-method robi to w jednej linijce:źródło
_({}).extend(obj1, obj2);
_.defaults(object, *defaults)
„Wypełnij puste i niezdefiniowane właściwości w obiekcie wartościami z obiektów domyślnych i zwróć obiekt”.var mergedObj = _.extend({}, obj1, obj2)
.Podobnie jak w jQuery ext (), masz tę samą funkcję w AngularJS :
źródło
Muszę dziś scalać obiekty, a to pytanie (i odpowiedzi) bardzo mi pomogło. Próbowałem niektórych odpowiedzi, ale żadna z nich nie pasowała do moich potrzeb, więc połączyłem niektóre odpowiedzi, sam coś dodałem i wymyśliłem nową funkcję scalania. Oto on:
Niektóre przykładowe zastosowania:
źródło
merge({}, t1, { key1: 1 })
?Możesz użyć właściwości rozkładania obiektów - obecnie propozycja ECMAScript etapu 3.
źródło
Podane rozwiązania powinny zostać zmodyfikowane, aby sprawdzić
source.hasOwnProperty(property)
wfor..in
pętlach przed przypisaniem - w przeciwnym razie kończy się kopiowanie właściwości całego łańcucha prototypów, co jest rzadko pożądane ...źródło
Scal właściwości N obiektów w jednym wierszu kodu
Object.assign
Metoda jest częścią standardu (2015) ES6 ECMAScript i robi dokładnie to, czego potrzebujesz. (IE
nie obsługiwane)Czytaj więcej...
Polyfill do obsługi starszych przeglądarek:
źródło
Objects.assign
zwraca scalony obiekt, którego inne odpowiedzi nie zawierają. To bardziej funkcjonalny styl programowania.Następujące dwa są prawdopodobnie dobrym punktem wyjścia. lodash ma również funkcję dostosowywania do tych specjalnych potrzeb!
_.extend
( http://underscorejs.org/#extend )_.merge
( https://lodash.com/docs#merge )źródło
Nawiasem mówiąc, wszystko, co robisz, to nadpisywanie właściwości, a nie łączenie ...
W ten sposób naprawdę scalono obszar obiektów JavaScript: tylko klucze w
to
obiekcie, które same nie są obiektami, zostaną zastąpione przezfrom
. Wszystko inne zostanie naprawdę połączone . Oczywiście możesz zmienić to zachowanie, aby nie zastępować niczego, co istnieje, jak tylko wtedyto[n] is undefined
, gdy itd ...:Stosowanie:
źródło
Oto moje dźgnięcie, które
Jest krótki :)
Przykład:
źródło
{}
jako pierwszy parametr, czy też funkcję zmodyfikować oryginalny obiekt. Dlatego jeśli zmieniszdst = {}
nadst = arguments[0]
to, zmieni się pierwszy obiekt, który przekazujesz do scalonego obiektutoString.call(src) == '[object Object]'
do sprawdzania, czy jest jakiś przedmiot, czy nie.typeof src
jest znacznie lepszy. Co więcej, przekształca tablice w obiekty (przynajmniej takie zachowanie mam na najnowszym chrome).Object.assign ()
ECMAScript 2015 (ES6)
Jest to nowa technologia, będąca częścią standardu ECMAScript 2015 (ES6). Specyfikacja tej technologii została sfinalizowana, ale sprawdź w tabeli kompatybilności status użytkowania i implementacji w różnych przeglądarkach.
Metoda Object.assign () służy do kopiowania wartości wszystkich możliwych do wyliczenia własnych właściwości z jednego lub więcej obiektów źródłowych do obiektu docelowego. Zwróci obiekt docelowy.
źródło
W przypadku niezbyt skomplikowanych obiektów możesz użyć JSON :
Pamiętaj, że w tym przykładzie „} {” nie może występować w ciągu znaków!
źródło
var so1 = JSON.stringify(obj1); var so2 = JSON.stringify(obj1); objMerge = so1.substr(0, so1.length-1)+","+so2.substr(1); console.info(objMerge);
function merge(obj1, obj2) { return JSON.parse((JSON.stringify(obj1) + JSON.stringify(obj2)) .replace(/\}\{/g, ',').replace(/,\}/g, '}').replace(/\{,/g, '{')); }
objMerge = JSON.parse((JSON.stringify(obj1) + JSON.stringify(obj2)).replace(/\}\{/, ", "));
Istnieje biblioteka nazywa
deepmerge
na GitHub : To wydaje się być coraz pewną trakcję. Jest samodzielny, dostępny zarówno za pośrednictwem menedżerów pakietów npm, jak i altana.Byłbym skłonny użyć tego lub ulepszyć to zamiast wklejać kod z odpowiedzi.
źródło
Najlepszym sposobem na to jest dodanie właściwej właściwości, której nie można wyliczyć za pomocą Object.defineProperty.
W ten sposób będziesz w stanie iterować właściwości obiektów bez nowo utworzonego „rozszerzenia”, które uzyskałbyś, gdybyś utworzył właściwość za pomocą Object.prototype.extend.
Mam nadzieję, że to pomaga:
Gdy już to zrobisz, możesz:
Właśnie napisałem o tym post na blogu: http://onemoredigit.com/post/1527191998/extending-objects-in-node-js
źródło
Możesz po prostu użyć jQuery
extend
Teraz
obj1
zawiera wszystkie wartościobj1
iobj2
źródło
jQuery.extend( target [, object1 ] [, objectN ] )
Prototyp ma to:
obj1.extend(obj2)
zrobi co chcesz.źródło
Object.prototype
a nieObject
... Dobry pomysł, czy nie, to jest to, coprototype.js
robi framework, więc jeśli go używasz, lub inny framework, który od niego zależy,Object.prototype
będzie już rozszerzonyextend
.Object.prototype
?Object.extend
nie będzie zakłócać twoich obiektów, po prostu dołącza funkcję doObject
obiektu. Iobj1.extend(obj2)
nie jest poprawnym sposobem na uruchomienie funkcji, użyjObject.extend(obj1, obj2)
insted** Scalanie obiektów jest proste w użyciu
Object.assign
lub...
operator rozkładania **Obiekty są scalane od prawej do lewej, co oznacza, że obiekty, które mają identyczne właściwości jak obiekty po ich prawej stronie, zostaną przesłonięte.
W tym przykładzie
obj2.car
zastępujeobj1.car
źródło
Tylko jeśli ktoś korzysta z Google Closure Library :
Podobna funkcja pomocnicza istnieje dla tablicy :
źródło
Rozszerzyłem metodę Davida Coalliera:
Jeśli zastąpienie jest fałszywe, żadna właściwość nie zostanie zastąpiona, ale zostaną dodane nowe właściwości.
Zastosowanie: obj.merge (scala ... [, zastępuj]);
Oto mój kod:
Przykłady i przypadki testowe:
Moja metoda równości znajduje się tutaj: Porównanie obiektów w JavaScript
źródło
W MooTools istnieje Object.merge () :
źródło
W Ext JS 4 można to zrobić w następujący sposób:
Zobacz scalanie (obiekt): Obiekt .
źródło
Wow ... to pierwszy post StackOverflow, który widziałem na wielu stronach. Przepraszamy za dodanie kolejnej „odpowiedzi”
Ta metoda jest dla ES5 i wcześniejszych - istnieje wiele innych odpowiedzi dotyczących ES6.
Nie widziałem żadnego „głębokiego” obiektu łączącego się za pomocą tej
arguments
właściwości. Oto moja odpowiedź - kompaktowa i rekurencyjna , pozwalająca na przekazywanie nieograniczonej liczby argumentów obiektowych:Skomentowana część jest opcjonalna. Po prostu pominie przekazane argumenty, które nie są obiektami (zapobiegając błędom).
Przykład:
źródło
Korzystanie z jQuery.extend () - Link
Korzystanie z _.merge () - Link
Korzystanie z _.extend () - Link
Korzystanie z Object.assign () ECMAScript 2015 (ES6) - Link
Wyjście wszystkich
źródło
Na podstawie odpowiedzi Markusa i vsync jest to wersja rozszerzona. Funkcja przyjmuje dowolną liczbę argumentów. Można go użyć do ustawienia właściwości w DOM węzłach i wykonywania głębokich kopii wartości. Jednak pierwszy argument podano przez odniesienie.
Aby wykryć węzeł DOM, używana jest funkcja isDOMNode () (patrz Pytanie o przepełnieniu stosu JavaScript isDOM - Jak sprawdzić, czy obiekt JavaScript jest obiektem DOM? )
Został przetestowany w Opera 11, Firefox 6, Internet Explorer 8 i Google Chrome 16.
Kod
Kilka przykładów
Ustaw innerHTML i styl elementu HTML
Scal tablice i obiekty. Zauważ, że niezdefiniowany może być użyty do zachowania wartości w lewej tablicy / obiekcie.
Każdy argument nie będący obiektem JavaScript (w tym null) zostanie zignorowany. Oprócz pierwszego argumentu odrzucane są również węzły DOM. Strzeż się, że np. Łańcuchy utworzone jak new String () są w rzeczywistości obiektami.
Jeśli chcesz scalić dwa obiekty w nowy (bez wpływu na jeden z dwóch), podaj {} jako pierwszy argument
Edytuj (przez ReaperSoon):
Aby także scalić tablice
źródło
źródło
Powinieneś użyć wartości domyślnych lodashDeep
źródło
W Underscore.js , aby scalić tablicę obiektów:
Powoduje to:
źródło