Powiedz, że mam przedmiot:
elmo = {
color: 'red',
annoying: true,
height: 'unknown',
meta: { one: '1', two: '2'}
};
Chcę zrobić nowy obiekt z podzbiorem jego właściwości.
// pseudo code
subset = elmo.slice('color', 'height')
//=> { color: 'red', height: 'unknown' }
Jak mogę to osiągnąć?
javascript
Christian Schlensker
źródło
źródło
emo.slice
na pierwszy rzut oka.Odpowiedzi:
Używanie destrukcji obiektów i skrótów własności
Od Philipp Kewisch:
źródło
let unwrap = ({a, c}) => ({a, c}); let unwrap2 = function({a, c}) { return { a, c }; }; let picked = unwrap({ a: 5, b: 6, c: 7 });
const { b, ...picked } = object
stworzyłobypicked
jak{ a: 5, c: 7 }
. Podałeś po prostu usunąć b. Twoja eslint prawdopodobnie będzie cię zirytowana za zadeklarowanie zmiennej, której nie używasz.Proponuję rzucić okiem na Lodash ; ma wiele świetnych funkcji narzędziowych.
Na przykład
pick()
byłoby dokładnie to, czego szukasz:skrzypce
źródło
_.omit(elmo, ['voice'])
aby zwrócić wszystko, alevoice
Jeśli używasz ES6, istnieje bardzo zwięzły sposób na zrobienie tego za pomocą destrukcji. Destrukturyzacja pozwala łatwo dodawać do obiektów za pomocą rozkładówki, ale umożliwia także tworzenie obiektów podzbiorów w ten sam sposób.
źródło
Chociaż jest to trochę bardziej szczegółowe, możesz osiągnąć to, co wszyscy inni zalecili podkreślenie / lodash 2 lata temu, używając Array.prototype.reduce .
Takie podejście rozwiązuje to z drugiej strony: zamiast brać obiekt i przekazywać do niego nazwy właściwości, aby je wyodrębnić, weź tablicę nazw właściwości i zredukuj je do nowego obiektu.
Chociaż w najprostszym przypadku jest bardziej szczegółowe, oddzwonienie tutaj jest dość przydatne, ponieważ możesz łatwo spełnić niektóre typowe wymagania, np. Zmienić właściwość „color” na „color” na nowym obiekcie, spłaszczyć tablice itp. - dowolne z rzeczy, które musisz zrobić, otrzymując obiekt z jednej usługi / biblioteki i budując nowy obiekt potrzebny gdzie indziej. Podczas gdy podkreślenie / lodash to doskonałe, dobrze zaimplementowane biblioteki lib, jest to moje preferowane podejście, polegające na mniejszym uzależnieniu od dostawcy, i prostsze, bardziej spójne podejście, gdy moja logika budowania podzbiorów staje się bardziej złożona.
edycja: wersja es7 tego samego:
edycja: Również dobry przykład curry! Niech funkcja „pick” zwróci inną funkcję.
Powyższe jest dość zbliżone do drugiej metody, z tą różnicą, że pozwala budować „próbnik” w locie. na przykład
Szczególnie schludne w tym podejściu jest to, że możesz łatwo wprowadzić wybrane „typy” w dowolne funkcje, np .
Array#map
:źródło
function showToy({ color, height }) {
objąłby tylko to, czego potrzebujesz.reduce
Podejście głównie sens kiedy upraszczania obiektów dla serializacji.const pick = (obj, props) => props.reduce((a, e) => (a[e] = obj[e], a), {});
fetch
), dlatego polecam dodanie komentarza wyjaśniającego użycie operatora przecinka.Restrukturyzacja ES6
Składnia destrukcyjna pozwala na destrukcję i rekombinację obiektu, z parametrami funkcji lub zmiennymi.
Ograniczeniem jest to, że lista kluczy jest predefiniowana, nie można ich wymienić jako ciągów, jak wspomniano w pytaniu. Restrukturyzacja staje się bardziej skomplikowana, jeśli klucz nie jest alfanumeryczny, np
foo_bar
.Minusem jest to, że wymaga to powielenia listy kluczy, skutkuje to pełnym kodem na wypadek, gdyby lista była długa. Ponieważ w tym przypadku destrukcja duplikuje składnię dosłowną obiektu, listę można skopiować i wkleić bez zmian.
Plusem jest to, że jest to wydajne rozwiązanie, które jest naturalne dla ES6.
IIFE
Zmienne tymczasowe
Lista ciągów
Dowolna lista wybranych kluczy składa się z ciągów znaków, zgodnie z wymaganiami pytania. Pozwala to nie predefiniować ich i używać zmiennych zawierających nazwy kluczy, takich jak
pick(obj, 'foo', someKey, ...moreKeys)
.Jedna linijka staje się krótsza z każdą edycją JS.
ES5
ES6
Lub z przecinkiem:
ES2019
ECMAScript 2017 ma,
Object.entries
aArray.prototype.includes
ECMAScript 2019 maObject.fromEntries
, mogą być wypełniane w razie potrzeby i ułatwiają zadanie:Jednowierszowy
pick
może być przepisany jako funkcja pomocnicza podobna do Lodash lubomit
gdy lista kluczy jest przekazywana przez argumenty:Uwaga na temat brakujących kluczy
Główną różnicą między destrukcją a tradycyjną funkcją typu Lodash
pick
jest to, że destrukcja obejmuje nieistniejące wybrane klucze oundefined
wartości w podzbiorze:To zachowanie może być pożądane lub nie. Nie można go zmienić dla składni destrukcyjnej.
Chociaż
pick
można zmienić, aby uwzględnić brakujące klucze, iterując zamiast tego listę wybranych kluczy:źródło
obj
zmienna jest zmienną przechowującą obiekt. Jeśli nazwa zmiennej jest inna, użyj jej zamiastobj
.Object.keys(obj)
. Senny.Nie ma nic takiego wbudowanego w bibliotekę podstawową, ale możesz to zrobić, używając restrukturyzacji obiektów ...
Możesz także napisać funkcję narzędziową zrób to ...
Biblioteki takie jak Lodash również mają
_.pick()
.źródło
Dodaję tę odpowiedź, ponieważ żadna z odpowiedzi nie została użyta
Comma operator
.Jest to bardzo łatwe
destructuring assignment
i,
operatoraZ pewnym ulepszeniem przypisywania właściwości dynamicznych mogłoby to wyglądać następująco:
źródło
'use strict'
.). DostajęReferenceError: a is not defined
.a
ic
- uważaj, aby nie nadpisywać losowo zmiennych lokalnych lub globalnych w zależności od kontekstu. (Przyjęta odpowiedź pozwala uniknąć tego problemu poprzez użycie dwóch zmiennych lokalnych w funkcji wbudowanej, która po natychmiastowym wykonaniu nie wchodzi w zakres).Jeszcze jedno rozwiązanie:
Wydaje mi się to bardziej czytelne niż jakakolwiek jak dotąd odpowiedź, ale może to tylko ja!
źródło
subset = {color: elmo.color, height: elmo.color}
, musiałbym mieć przynajmniej ... cóż, może dziesięciocentówkę.Możesz także użyć Lodash .
Uzupełniając, powiedzmy, że masz tablicę „elmo”:
Jeśli chcesz tego samego zachowania, używając lodash, po prostu:
źródło
Jak opisano w tym pytaniu, przekształcanie w zmienne o nazwach dynamicznych jest niemożliwe w JavaScript .
Aby dynamicznie ustawiać klucze , możesz użyć funkcji zmniejszania bez mutowania obiektu w następujący sposób:
poniżej znajduje się wersja wykorzystująca redukcję z pojedynczym klonem (aktualizacja wartości początkowej przekazana w celu zmniejszenia).
źródło
Rozwiązanie TypeScript:
Informacje o pisaniu pozwalają nawet na automatyczne uzupełnianie:
Problem zgłosili DefinitelyTyped dla
U extends keyof T
sztuczki!źródło
Użyj
pick
metody biblioteki lodash, jeśli już z niej korzystasz.https://lodash.com/docs/4.17.10#pick
źródło
Dynamiczne rozwiązanie
Pokaż fragment kodu
źródło
Po prostu inny sposób ...
Możesz użyć tej funkcji z tablicą Objects =)
źródło
Co powiesz na:
źródło
false
(lub fałsz). jsfiddle.net/nfAs8keys[i] in obj
.Działa to dla mnie w konsoli Chrome. Masz z tym jakiś problem?
źródło
Przydział destrukcyjny z właściwościami dynamicznymi
To rozwiązanie dotyczy nie tylko konkretnego przykładu, ale ma bardziej ogólne zastosowanie:
Możesz łatwo zdefiniować
subset4
itp., Aby uwzględnić więcej właściwości.źródło
Dobry stary
Array.prototype.reduce
:w tej odpowiedzi użyto magicznego przecinka, również: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator
jeśli chcesz się naprawdę zachwycić, jest to bardziej kompaktowe:
Łącząc to wszystko w funkcję wielokrotnego użytku:
źródło
konwertuj argumenty na tablicę
użyj,
Array.forEach()
aby wybrać właściwośćźródło
źródło
Próbować
źródło
Dodając moje 2 centy do odpowiedzi Iwana Nosowa :
W moim przypadku potrzebowałem wielu kluczy do „wycięcia” z obiektu, więc staje się brzydki bardzo szybko i niezbyt dynamicznym rozwiązaniem:
Oto dynamiczne rozwiązanie wykorzystujące eval:
źródło
możesz rozszerzyć jquery, jeśli chcesz tutaj, przykładowy kod dla jednego wycinka:
oto skrzypce dla tego samego: http://jsfiddle.net/w633z/
źródło