JavaScript: filter() für Objekte
ECMAScript 5 hat die filter()
Prototyp für Array
Typen, aber nicht Object
Typen, wenn ich das richtig verstehe.
Wie würde ich das umsetzen, eine filter()
für Object
s in JavaScript?
Sagen wir, ich habe dieses Objekt:
var foo = {
bar: "Yes"
};
Und ich will schreiben ein filter()
arbeiten 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;
};
Funktioniert das wenn ich es in die folgende demo, aber wenn ich es auf meiner Website mit jQuery 1.5 und jQuery-UI-1.8.9, bekomme ich den JavaScript Fehler in FireBug.
JS:
Object.prototype.filter = function(predicate) {
var result = {};
for (key in this) {
if (this.hasOwnProperty(key) && !predicate(this[key])) {
console.log("copying");
result[key] = this[key];
}
}
return result;
};
var foo = {
bar: "Yes",
moo: undefined
};
foo = foo.filter(function(property) {
return typeof property === "undefined";
});
document.getElementById('disp').innerHTML = JSON.stringify(foo, undefined, ' ');
console.log(foo);
CSS:
#disp {
white-space: pre;
font-family: monospace
}
HTML:
<div id="disp"></div>
- Welche Fehler haben Sie speziell?
- Welche Fehler sind Sie immer? Posten Sie, wenn möglich 🙂
- Es ist eine etwas zweideutige Geschichte wrt jQuery und Skripte erweitern
Object.prototype
: bugs.jquery.com/ticket/2721
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nie verlängern
Object.prototype
.Schreckliche Dinge passiert in Ihrem code. Dinge brechen. Vergrößern Sie alle Objekt-Typen, einschließlich Objekt-Literale.
Hier ist ein schnelles Beispiel können Sie versuchen:
Stattdessen erstellen Sie eine Funktion, die Sie übergeben das Objekt.
:)
key
variable in derfor-in
Schleife 😉Object.prototype
, sondern legen Sie einfach die Funktion aufObject
. Zweite, dies ist der OP-code. Klar OP ist beabsichtigt, haben.filter()
so sein, dass es Filter aus die positiven Ergebnisse. In anderen Worten, es ist ein negativ-filter, wo ein positiver Rückgabewert bedeutet, dass es ausgeschlossen aus dem Ergebnis. Wenn man sich die jsFiddle Beispiel, er ist ein herausfiltern der vorhandene Eigenschaften, dieundefined
.Object.prototype
. Aus der Frage: "Das funktioniert..., aber wenn ich es auf meine Seite..., ich bekomme JavaScript-Fehler" Wenn der OP entscheidet, zu implementieren.filter()
mit dem anderen Verhalten, die vonArray.prototpe.filter
, das ist bis zu ihm/Ihr. Bitte hinterlassen Sie einen Kommentar unter die Frage, wenn Sie möchten, Benachrichtigen OP, dass der code falsch ist, aber erzähl mir nicht, dass ich bin etwas falsch, wenn es nicht mein code.for (key in obj){if obj.hasOwnProperty(key){....}}
AFAIK, alle Schlüssel in dieser for-Schleife ist ein enumerable-Eigenschaft obj, und daher obj.hasOwnProperty wird immer true zurück. Was bin ich? In welchen Fällen wird es false zurück?Zunächst es gilt als schlechte Praxis zu erweitern
- Objekt.prototype
. Geben Sie stattdessen Ihre Funktion als utility-Funktion aufObject
, so wie es bereitsObject.keys
,Object.assign
,Object.is
...usw.Ich biete hier mehrere Lösungen:
reduce
undObject.keys
Object.assign
map
- und spread-syntax anstelle vonreduce
Object.entries
undObject.fromEntries
1. Mit
reduce
undObject.keys
Mit
reduzieren
und- Objekt.keys
zu implementieren, die die gewünschten filter (mit ES6 Pfeil-syntax):JS:
Beachten Sie, dass im obigen code
predicate
muss ein Einbeziehung Zustand (im Gegensatz zu den Ausschluss Bedingung, die der OP verwendet), so dass es im Einklang mit, wieArray.der Prototyp.- filter
funktioniert.2. Wie (1), in Kombination mit
Object.assign
In der obigen Lösung die Komma-operator wird in der
reduce
Teil die Rückkehr der mutiertenres
Objekt. Natürlich kann dies geschrieben werden als zwei-Anweisungen anstelle eines Ausdrucks, aber das letztere ist übersichtlicher. Dies zu tun, ohne den Komma-operator, den Sie verwenden konnten,- Objekt.zuweisen
statt, die hat Rückkehr der mutierten Objekt:JS:
3. Mit
map
- und spread-syntax anstelle vonreduce
Hier bewegen wir die
Object.assign
Aufruf aus der Schleife, so ist es nur einmal gemacht, und übergeben Sie die einzelnen Tasten als separate Argumente (mit dem verbreiten syntax):JS:
4. Mit
Object.entries
undObject.fromEntries
Als die Lösung übersetzt das Objekt in einem Zwischenspeicher array und wandelt dann zurück zu einem einfachen Objekt, wäre es sinnvoll zu machen Verwendung von
- Objekt.Einträge
(ES2017) und eine Methode zu verwenden, das bewirkt das Gegenteil (d.h. erstellen Sie ein Objekt aus einem array von Schlüssel/Wert-Paaren). Zu der Zeit des Schreibens der- Objekt.fromEntries
Vorschlag ist auf Stufe 3. Firefox und zuletzt Chrome haben umgesetzt. Ansonsten ein polyfill verwendet werden kann.Führt es zu diesen beiden "one-liner" - Verfahren auf
Object
(einschließlich der polyfill):JS:
Dem Prädikat-Funktion wird ein Schlüssel/Wert-paar als argument hier, das ist ein bisschen anders, aber es ermöglicht mehr Möglichkeiten in der Prädikat-Funktion der Logik.
x => x.Expression.Filters.Filter
.Filter
ist am Ende, aber wenn es funktioniert, müssen Sie Sie aufrufen (x => x.Expression.Filters.Filter()
)predicate(obj[key], key, obj)
Wenn Sie bereit sind, zu verwenden Unterstrich oder lodash, die Sie verwenden können,
pick
(oder Ihr Gegenteil,ohne
).Beispiele von Unterstrich die docs:
Oder mit einem callback (für lodash, verwenden Sie pickBy):
Wie patrick schon gesagt das ist eine schlechte Idee, da es fast zweifellos Pause 3rd-party-code, den Sie sich jemals wünschen könnte zu verwenden.
Alle Bibliotheken wie jquery oder prototype brechen, wenn Sie erweitern
Object.prototype
, der Grund dafür ist, dass faul iteration über Objekte (ohnehasOwnProperty
überprüft) brechen, da die Funktionen, die Sie hinzufügen, werden Teil der iteration.Erstellt habe ich eine
Object.filter()
die nicht nur filter durch eine Funktion, aber akzeptiert auch ein array von Tasten umfassen. Der optionale Dritte parameter erlauben, Sie zum umkehren der filter.Gegeben:
Array:
Funktion:
Code
Haftungsausschluss: ich entschied mich für die Verwendung von Ext JS core für die Kürze. Habe nicht das Gefühl, es war notwendig zu schreiben, geben Sie Steine für Objekt-Typen, denn es war nicht Teil der Frage.
JS:
CSS:
HTML:
ES6 Ansatz...
Stellen Sie sich vor, dieses Objekt unter:
Erstellen Sie eine Funktion:
Und nennen es:
und zurück:
!predicate
im eigenen code).Gegeben
dann :
JS:
Wie etwa:
... Oder
Meine eigenwillige Lösung:
Testfälle:
https://gist.github.com/khullah/872d5a174108823159d845cc5baba337
Wie alle sagten, nicht Schraube herum mit Prototypen. Stattdessen einfach eine Funktion schreiben, die dies tun. Hier ist meine version mit
lodash
:In diesen Fällen verwende ich das jquery -$.Karte, die den Umgang mit Objekten. Wie bereits erwähnt auf andere Antworten, es ist nicht eine gute Praxis zu ändern nativen Prototypen (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain#Bad_practice_Extension_of_native_prototypes)
Unten ist ein Beispiel der Filterung nur durch die überprüfung einer Eigenschaft des Objekts. Es gibt das eigene Objekt, wenn Ihre Bedingung wahr ist oder gibt
undefined
wenn nicht. Dieundefined
Eigentum machen, dass der Datensatz verschwindet aus Ihrem Objekt-Liste;$.map
können, ein Objekt aufzunehmen, aber es gibt ein array zurück, so dass die ursprünglichen Namen der Eigenschaft verloren. Der OP braucht eine gefilterte plain-Objekt.