ECMAScript 5 ma filter()
prototyp dla Array
typów, ale nie Object
typów, jeśli dobrze rozumiem.
Jak zaimplementować filter()
for Object
w JavaScript?
Powiedzmy, że mam ten obiekt:
var foo = {
bar: "Yes"
};
I chcę napisać, filter()
który działa na Object
s:
Object.prototype.filter = function(predicate) {
var result = {};
for (key in this) {
if (this.hasOwnProperty(key) && !predicate(this[key])) {
result[key] = this[key];
}
}
return result;
};
Działa to, gdy używam go w poniższej wersji demonstracyjnej, ale kiedy dodam go do mojej witryny korzystającej z jQuery 1.5 i jQuery UI 1.8.9, otrzymuję błędy JavaScript w FireBug.
javascript
jquery
object
filtering
AgileMeansDoAsLittleAsPossible
źródło
źródło
Object.prototype
: bugs.jquery.com/ticket/2721Odpowiedzi:
Nigdy nie przedłużaj
Object.prototype
.W twoim kodzie pojawią się okropne rzeczy. Wszystko się zepsuje. Rozszerzasz wszystkie typy obiektów, w tym literały obiektów.
Oto szybki przykład, który możesz wypróbować:
Zamiast tego utwórz funkcję, którą przekazujesz obiekt.
źródło
Object.prototype
, ale po prostu umieszczanie tej funkcjiObject
. Po drugie, jest to kod PO . Najwyraźniej intencją OP jest.filter()
takie filtrowanie pozytywnych wyników. Innymi słowy, jest to filtr ujemny, w którym dodatnia wartość zwracana oznacza, że jest wykluczona z wyniku. Jeśli spojrzysz na przykład jsFiddle, odfiltrowuje on istniejące właściwościundefined
.Object.prototype
. Z pytania: „Działa to ..., ale kiedy dodam go do mojej witryny ..., dostaję błędy JavaScript”. Jeśli OP zdecyduje się zastosować.filter()
odwrotne zachowanieArray.prototpe.filter
, to zależy od niego. Zostaw komentarz pod pytaniem, jeśli chcesz powiadomić OP, że kod jest nieprawidłowy, ale nie mów mi, że robię to źle, jeśli nie jest to mój kod.Przede wszystkim przedłużanie uważa się za złą praktykę
Object.prototype
. Zamiast podać funkcję jako funkcji użyteczności naObject
, jak już tam sąObject.keys
,Object.assign
,Object.is
, ... etc.Podaję tutaj kilka rozwiązań:
reduce
iObject.keys
Object.assign
map
i rozkładanie składni zamiastreduce
Object.entries
iObject.fromEntries
1. Używanie
reduce
iObject.keys
Za pomocą
reduce
iObject.keys
aby zaimplementować żądany filtr (używając składni strzałek ES6 ):Zauważ, że w powyższym kodzie
predicate
musi być warunek włączenia (w przeciwieństwie do warunku wyłączenia zastosowany OP), aby był zgodny z tym, jakArray.prototype.filter
działa.2. Jak (1) w połączeniu z
Object.assign
W powyższym rozwiązaniu operator przecinka jest używany w
reduce
części, aby zwrócić zmutowanyres
obiekt. Można to oczywiście zapisać jako dwie wypowiedzi zamiast jednego wyrażenia, ale to drugie jest bardziej zwięzłe. Aby to zrobić bez operatora przecinek, można użyćObject.assign
zamiast tego, który ma powrócić zmutowaną obiektu:3. Używanie
map
i rozkładanie składni zamiastreduce
Tutaj przenosimy
Object.assign
wywołanie z pętli, więc jest ono wykonywane tylko raz i przekazujemy poszczególne klucze jako osobne argumenty (przy użyciu składni rozszerzonej ):4. Używanie
Object.entries
iObject.fromEntries
Ponieważ rozwiązanie przekształca obiekt w tablicę pośrednią, a następnie przekształca go z powrotem w zwykły obiekt, przydatne byłoby skorzystanie z
Object.entries
(ES2017) i odwrotnie (tj. Utworzenie obiektu z tablicy par klucz / wartość ) za pomocąObject.fromEntries
( ES2019).Prowadzi to do tej metody „one-liner” na
Object
:Funkcja predykatu otrzymuje tutaj argument klucz / wartość, co jest nieco inne, ale pozwala na więcej możliwości w logice funkcji predykatu.
źródło
x => x.Expression.Filters.Filter
.Filter
jest na końcu, ale jeśli jest to funkcja, musisz ją wywołać (x => x.Expression.Filters.Filter()
)Jeśli chcesz użyć podkreślenia lub lodash , możesz użyć
pick
(lub odwrotnieomit
).Przykłady z dokumentów podkreślenia:
Lub z oddzwanianiem (dla lodash , użyj pickBy ):
źródło
Podejście ES6 ...
Wyobraź sobie, że masz ten obiekt poniżej:
Utwórz funkcję:
I nazwij to:
i zwróci :
źródło
!predicate
ich własnym kodem).Jak już stwierdził Patrick, jest to zły pomysł, ponieważ prawie na pewno złamie dowolny kod innej firmy, którego kiedykolwiek będziesz chciał użyć.
Wszystkie biblioteki, takie jak jquery lub prototyp, ulegną awarii, jeśli się rozszerzysz
Object.prototype
. Powodem jest to, że leniwa iteracja obiektów (bezhasOwnProperty
sprawdzania) ulegnie awarii, ponieważ dodane funkcje będą częścią iteracji.źródło
Co powiesz na:
Lub...
źródło
Dany
następnie :
Pokaż fragment kodu
źródło
Stworzyłem taki,
Object.filter()
który nie tylko filtruje według funkcji, ale także akceptuje tablicę kluczy do włączenia. Opcjonalny trzeci parametr umożliwia odwrócenie filtru.Dany:
Szyk:
Funkcjonować:
Kod
Oświadczenie : postanowiłem użyć rdzenia Ext JS dla zwięzłości. Nie czułem, że konieczne jest pisanie kontrolerów typów dla typów obiektów, ponieważ nie było to częścią pytania.
źródło
Moje wymyślone rozwiązanie:
Przypadki testowe:
https://gist.github.com/bernardoadc/872d5a174108823159d845cc5baba337
źródło
Rozwiązanie w Vanilla JS od roku 2020.
Możesz filtrować
romNumbers
obiekt według klucza:Lub filtruj
romNumbers
obiekt według wartości:źródło
Jeśli chcesz zmutować ten sam obiekt, a nie utworzyć nowy.
Poniższy przykład usunie wszystkie 0 lub puste wartości:
źródło
Jak wszyscy mówili, nie psuj prototypu. Zamiast tego po prostu napisz funkcję, aby to zrobić. Oto moja wersja z
lodash
:źródło
Używam tego, kiedy go potrzebuję:
źródło
W takich przypadkach używam jquery $ .map, która może obsługiwać obiekty. Jak wspomniano w innych odpowiedziach, zmiana natywnych prototypów nie jest dobrą praktyką ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain#Bad_practice_Extension_of_native_prototypes )
Poniżej znajduje się przykład filtrowania tylko poprzez sprawdzenie właściwości obiektu. Zwraca własny obiekt, jeśli warunek jest spełniony, lub zwraca,
undefined
jeśli nie.undefined
Nieruchomość sprawi, że rekord zniknie z listy obiektów;źródło
$.map
może przyjąć obiekt, ale zwraca tablicę, więc oryginalne nazwy właściwości zostaną utracone. OP potrzebuje przefiltrowanego zwykłego obiektu.