ECMAScript 5 hat den filter()
Prototyp für Array
Typen, aber keine Object
Typen, wenn ich das richtig verstehe.
Wie würde ich ein filter()
for Object
s in JavaScript implementieren ?
Angenommen, ich habe dieses Objekt:
var foo = {
bar: "Yes"
};
Und ich möchte eine schreiben filter()
, die auf Object
s funktioniert :
Object.prototype.filter = function(predicate) {
var result = {};
for (key in this) {
if (this.hasOwnProperty(key) && !predicate(this[key])) {
result[key] = this[key];
}
}
return result;
};
Dies funktioniert, wenn ich es in der folgenden Demo verwende. Wenn ich es jedoch zu meiner Site hinzufüge, die jQuery 1.5 und jQuery UI 1.8.9 verwendet, werden in FireBug JavaScript-Fehler angezeigt.
javascript
jquery
object
filtering
AgileMeansDoAsLittleAsPossible
quelle
quelle
Object.prototype
: bugs.jquery.com/ticket/2721Antworten:
Niemals verlängern
Object.prototype
.Schreckliche Dinge werden mit Ihrem Code passieren. Die Dinge werden brechen. Sie erweitern alle Objekttypen, einschließlich Objektliterale.
Hier ist ein kurzes Beispiel, das Sie ausprobieren können:
Erstellen Sie stattdessen eine Funktion, mit der Sie das Objekt übergeben.
quelle
Object.prototype
, sondern nur die Funktion zu platzierenObject
. Zweitens ist dies der OP-Code . Offensichtlich OP Absicht ist zu haben.filter()
sein , so dass es filtert die positiven Ergebnisse. Mit anderen Worten, es ist ein negativer Filter, bei dem ein positiver Rückgabewert bedeutet, dass er vom Ergebnis ausgeschlossen ist. Wenn Sie sich das Beispiel jsFiddle ansehen, filtert er vorhandene Eigenschaften herausundefined
.Object.prototype
. Aus der Frage: "Das funktioniert ... aber wenn ich es meiner Site hinzufüge ... erhalte ich JavaScript-Fehler" Wenn OP beschließt, ein.filter()
mit dem entgegengesetzten Verhalten von zu implementierenArray.prototpe.filter
, liegt es an ihm / ihr. Bitte hinterlassen Sie einen Kommentar unter der Frage, wenn Sie OP benachrichtigen möchten, dass der Code falsch ist, aber sagen Sie mir nicht, dass ich es falsch mache, wenn es nicht mein Code ist.Zuallererst wird es als schlechte Praxis angesehen, zu verlängern
Object.prototype
. Stattdessen geben Sie Ihre Funktion als Nutzenfunktion aufObject
, so wie es bereits sindObject.keys
,Object.assign
,Object.is
, ... etc.Ich biete hier verschiedene Lösungen an:
reduce
undObject.keys
Object.assign
map
und Verbreiten der Syntax anstelle vonreduce
Object.entries
undObject.fromEntries
1. Verwenden von
reduce
undObject.keys
Mit
reduce
undObject.keys
zum Implementieren des gewünschten Filters (unter Verwendung der ES6- Pfeilsyntax ):Beachten Sie, dass der obige Code
predicate
eine Einschlussbedingung sein muss (im Gegensatz zu der Ausschlussbedingung , die das OP verwendet), damit sie mit der FunktionsweiseArray.prototype.filter
übereinstimmt.2. Wie (1) in Kombination mit
Object.assign
In der obigen Lösung wird der Kommaoperator in der verwendet
reduce
Teil verwendet, um das mutierteres
Objekt zurückzugeben. Dies könnte natürlich als zwei Aussagen anstelle eines Ausdrucks geschrieben werden, aber letzterer ist prägnanter. Um es ohne Komma - Operator zu tun, könnten SieObject.assign
stattdessen, die nicht das mutierte Objekt zurückgeben:3. Verwenden
map
und verbreiten Sie die Syntax anstelle vonreduce
Hier verschieben wir den
Object.assign
Aufruf aus der Schleife, sodass er nur einmal ausgeführt wird, und übergeben ihm die einzelnen Schlüssel als separate Argumente (unter Verwendung der Spread-Syntax ):4. Verwenden von
Object.entries
undObject.fromEntries
Da die Lösung das Objekt in ein Zwischenarray übersetzt und dieses dann wieder in ein einfaches Objekt konvertiert, wäre es nützlich, es zu verwenden
Object.entries
(ES2017) und das Gegenteil (dh ein Objekt aus einem Array von Schlüssel / Wert-Paaren erstellen ) mitObject.fromEntries
( ES2019).Es führt zu dieser "Einzeiler" -Methode auf
Object
:Die Prädikatfunktion erhält hier ein Schlüssel / Wert-Paar als Argument, was etwas anders ist, aber mehr Möglichkeiten in der Logik der Prädikatfunktion bietet.
quelle
x => x.Expression.Filters.Filter
.Filter
am Ende ist, aber wenn es eine Funktion ist, müssen Sie es (x => x.Expression.Filters.Filter()
)Wenn Sie bereit sind, Unterstrich oder Lodash zu verwenden , können Sie
pick
(oder das Gegenteilomit
) verwenden.Beispiele aus den Dokumenten des Unterstrichs:
Oder mit einem Rückruf (z lodash verwenden Sie pickBy ):
quelle
ES6- Ansatz ...
Stellen Sie sich vor, Sie haben dieses Objekt unten:
Erstellen Sie eine Funktion:
Und nenne es:
und wird zurückkehren :
quelle
!predicate
in ihrem eigenen Code).Wie Patrick bereits sagte, ist dies eine schlechte Idee, da dadurch mit ziemlicher Sicherheit jeder Code von Drittanbietern beschädigt wird, den Sie jemals verwenden möchten.
Alle Bibliotheken wie jquery oder prototype werden beim Erweitern unterbrochen.
Object.prototype
Der Grund dafür ist, dass die verzögerte Iteration über Objekte (ohnehasOwnProperty
Überprüfungen) unterbrochen wird, da die von Ihnen hinzugefügten Funktionen Teil der Iteration sind.quelle
Wie wäre es mit:
Oder...
quelle
Gegeben
dann :
Code-Snippet anzeigen
quelle
Ich habe eine erstellt
Object.filter()
die nicht nur nach einer Funktion filtert, sondern auch ein Array von Schlüsseln akzeptiert, die eingeschlossen werden sollen. Mit dem optionalen dritten Parameter können Sie den Filter invertieren.Gegeben:
Array:
Funktion:
Code
Haftungsausschluss : Der Kürze halber habe ich mich für Ext JS Core entschieden. Ich hatte nicht das Gefühl, dass es notwendig war, Typprüfungen für Objekttypen zu schreiben, da dies nicht Teil der Frage war.
quelle
Meine meinungsgebundene Lösung:
Testfälle:
https://gist.github.com/bernardoadc/872d5a174108823159d845cc5baba337
quelle
Wenn Sie dasselbe Objekt mutieren möchten, anstatt ein neues zu erstellen.
Im folgenden Beispiel werden alle 0 oder leeren Werte gelöscht:
quelle
Lösung in Vanilla JS ab dem Jahr 2020.
Sie können das
romNumbers
Objekt nach Schlüssel filtern :Oder filtern Sie das
romNumbers
Objekt nach Wert:quelle
Wie alle sagten, schrauben Sie nicht mit Prototypen herum. Schreiben Sie stattdessen einfach eine Funktion, um dies zu tun. Hier ist meine Version mit
lodash
:quelle
Ich benutze dies, wenn ich es brauche:
quelle
In diesen Fällen verwende ich die jquery $ .map, die Objekte verarbeiten kann. Wie in anderen Antworten erwähnt, ist es keine gute Vorgehensweise, native Prototypen zu ändern ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain#Bad_practice_Extension_of_native_prototypes) ).
Im Folgenden finden Sie ein Beispiel für das Filtern, indem Sie einige Eigenschaften Ihres Objekts überprüfen. Es gibt das eigene Objekt zurück, wenn Ihre Bedingung erfüllt ist, oder gibt es zurück,
undefined
wenn nicht. Durch dieundefined
Eigenschaft wird dieser Datensatz aus Ihrer Objektliste entfernt.quelle
$.map
kann ein Objekt aufnehmen, gibt jedoch ein Array zurück, sodass die ursprünglichen Eigenschaftsnamen verloren gehen. Das OP benötigt ein gefiltertes einfaches Objekt.