Wie übergebe ich einen zusätzlichen Parameter an die Rückruffunktion in der Javascript .filter () -Methode?

104

Ich möchte jede Zeichenfolge in einem Array mit einer bestimmten Zeichenfolge vergleichen. Meine aktuelle Implementierung ist:

function startsWith(element) {
    return element.indexOf(wordToCompare) === 0;
}
addressBook.filter(startsWith);

Diese einfache Funktion funktioniert, aber nur, weil wordToCompare gerade als globale Variable festgelegt wird, aber ich möchte dies natürlich vermeiden und als Parameter übergeben. Mein Problem ist, dass ich nicht sicher bin, wie StartsWith () definiert werden soll, sodass ein zusätzlicher Parameter akzeptiert wird, da ich nicht wirklich verstehe, wie die Standardparameter übergeben werden. Ich habe all die verschiedenen Möglichkeiten ausprobiert, die mir einfallen, und keine davon funktioniert.

Wenn Sie auch erklären könnten, wie die an 'eingebaute' Rückruffunktionen übergebenen Parameter funktionieren (Entschuldigung, ich kenne keinen besseren Begriff für diese), wäre das großartig

agente_secreto
quelle

Antworten:

152

Machen Sie startsWithdas Wort akzeptieren gegen vergleichen und eine Funktion zurückgeben , die dann als Filter / Callback - Funktion verwendet werden soll:

function startsWith(wordToCompare) {
    return function(element) {
        return element.indexOf(wordToCompare) === 0;
    }
}

addressBook.filter(startsWith(wordToCompare));

Eine andere Möglichkeit wäre, Function.prototype.bind [MDN] zu verwenden (nur in Browsern verfügbar, die ECMAScript 5 unterstützen, folgen Sie einem Link für einen Shim für ältere Browser) und das erste Argument zu "korrigieren":

function startsWith(wordToCompare, element) {
    return element.indexOf(wordToCompare) === 0;
}

addressBook.filter(startsWith.bind(this, wordToCompare));

Ich verstehe nicht wirklich, wie die Standardparameter übergeben werden

Daran ist nichts Besonderes. Ruft irgendwann filtereinfach den Rückruf auf und übergibt das aktuelle Element des Arrays. Es handelt sich also um eine Funktion, die eine andere Funktion aufruft, in diesem Fall den Rückruf, den Sie als Argument übergeben.

Hier ist ein Beispiel für eine ähnliche Funktion:

function filter(array, callback) {
    var result = [];
    for(var i = 0, l = array.length; i < l; i++) {
        if(callback(array[i])) {  // here callback is called with the current element
            result.push(array[i]);
        }
    }
    return result;
}
Felix Kling
quelle
1
Ok, jetzt verstehe ich. Ich habe versucht, die Parameter direkt an die Rückruffunktion zu übergeben ... Ich muss wirklich an meinem JavaScript arbeiten. Vielen Dank Felix, Ihre Antwort ist sehr hilfreich
agente_secreto
Was ist mit zusätzlichen Argumenten? Ich habe versucht, eine Reihe von Argumenten zu übergeben, aber das scheint zu scheitern
Geotheory
@geotheory: was ist mit ihnen? Sie übergeben mehrere Argumente wie an jede andere Funktion.
Felix Kling
bind (this) after function name zusammen mit filter () chaining hat mir geholfen, diese interne Funktion zu verwenden. Vielen Dank.
Sagar Khatri
108

Der zweite Parameter des Filters setzt dies innerhalb des Rückrufs.

arr.filter(callback[, thisArg])

Sie könnten also so etwas tun wie:

function startsWith(element) {
    return element.indexOf(this) === 0;
}
addressBook.filter(startsWith, wordToCompare);
Jeff
quelle
7
Ich fand das die beste Antwort.
Jeaf Gilbert
Jetzt wird das neue Array dem wordToCompare-Objekt zugewiesen, oder? Wie kann später mit dem wordToCompare-Objekt auf das neue Array zugegriffen werden?
Badhon Jain
beste Antwort. funktioniert perfekt sowohl für Filter als auch für Fund. Und ist pro WC3-Dokumentation für beide: thisValue - Optional. Ein Wert, der an die Funktion übergeben werden soll, um als "dieser" Wert verwendet zu werden. Wenn dieser Parameter leer ist, wird der Wert "undefined" als "this" -Wert übergeben
richaa
1
@ TarekEldeeb übergeben Sie einfach ein Objekt, das Sie machen{one: 'haha', two:'hoho'}
toddmo
2
Dies ist ein großartiges Beispiel dafür, wie es große Unterschiede zwischen den Antworten
hinsichtlich der
13

Wenn Sie nach einer ES6-Alternative mit Pfeilfunktionen suchen, können Sie Folgendes tun.

let startsWith = wordToCompare => (element, index, array) => {
  return element.indexOf(wordToCompare) === 0;
}

// where word would be your argument
let result = addressBook.filter(startsWith("word"));

Aktualisierte Version mit enthält :

const startsWith = wordToCompare => (element, index, array) => {
  return element.includes(wordToCompare);
}
jhamPac
quelle
Gibt es eine Möglichkeit, einen anderen Parameter als Element, Index und Array zu übergeben? Zum Beispiel möchte ich eine X-Variable übergeben.
Leandrotk
@eandrotk in diesem Fall "wordToCompare" ist die "X" -Variable, die übergeben werden soll.
GetBackerZ
11
function startsWith(element, wordToCompare) {
    return element.indexOf(wordToCompare) === 0;
}

// ...
var word = "SOMETHING";

addressBook.filter(function(element){
    return startsWith(element, word);
});
James Montagne
quelle
4

Sie können die Pfeilfunktion in einem Filter folgendermaßen verwenden:

result = addressBook.filter(element => element.indexOf(wordToCompare) === 0);

Pfeilfunktionen auf MDN

Ein Pfeilfunktionsausdruck hat im Vergleich zu Funktionsausdrücken eine kürzere Syntax und bindet diesen Wert lexikalisch (bindet nicht seinen eigenen Wert this, arguments, super oder new.target). Pfeilfunktionen sind immer anonym. Diese Funktionsausdrücke eignen sich am besten für Nicht-Methodenfunktionen und können nicht als Konstruktoren verwendet werden.

oddRaven
quelle
Hinweis: Nicht unterstützt auf IE
Luis Lavieri
1

Für alle, die sich fragen, warum ihre Fettpfeilfunktion ignoriert wird [, thisArg], zB warum

["DOG", "CAT", "DOG"].filter(animal => animal === this, "DOG") kehrt zurück []

Dies liegt daran, dass thisinnerhalb dieser Pfeilfunktionen beim Erstellen der Funktion gebunden und auf den Wert von thisin dem umfassenderen Bereich festgelegt werden, sodass das thisArgArgument ignoriert wird. Ich habe das ziemlich einfach umgangen, indem ich eine neue Variable in einem übergeordneten Bereich deklariert habe:

let bestPet = "DOG"; ["DOG", "CAT", "DOG"].filter(animal => animal === bestPet); => ["DOG", "DOG"]

Hier ist ein Link zu weiteren Informationen: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this

JKettler
quelle
0

basierend auf oddRaven Antwort und https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

Ich habe es auf 2 verschiedene Arten gemacht. 1) Funktionsweise verwenden. 2) Inline-Verwendung.

//Here  is sample codes : 

var templateList   = [
{ name: "name1", index: 1, dimension: 1 }  ,
{ name: "name2", index: 2, dimension: 1 }  ,
{ name: "name3", index: 3, dimension: 2 }  ];


//Method 1) using function : 

function getDimension1(obj) {
                if (obj.dimension === 1) // This is hardcoded . 
                    return true;
                else return false;
            } 

var tl = templateList.filter(getDimension1); // it will return 2 results. 1st and 2nd objects. 
console.log(tl) ;

//Method 2) using inline way 
var tl3 = templateList.filter(element => element.index === 1 || element.dimension === 2  ); 
// it will return 1st and 3rd objects 
console.log(tl3) ;

Ashish
quelle
0

Es gibt eine einfache Möglichkeit, die Filterfunktion zu verwenden, auf alle Parameter zuzugreifen und sie nicht zu komplizieren.

Sofern thisArg des Rückrufs nicht auf einen anderen Bereichsfilter festgelegt ist, wird kein eigener Bereich erstellt, und wir können auf Parameter innerhalb des aktuellen Bereichs zugreifen. Wir können 'this' festlegen, um einen anderen Bereich zu definieren, um bei Bedarf auf andere Werte zuzugreifen. Standardmäßig wird jedoch der Bereich festgelegt, von dem aus aufgerufen wird. Sie können sehen, dass dies für Winkelbereiche in diesem Stapel verwendet wird .

Die Verwendung von indexOf macht den Zweck des Filters zunichte und erhöht den Overhead. Der Filter durchläuft das Array bereits. Warum müssen wir es dann erneut durchlaufen? Wir können es stattdessen zu einer einfachen reinen Funktion machen .

Hier ist ein Anwendungsszenario innerhalb einer React-Klassenmethode, in der der Status ein Array mit dem Namen items enthält . Mithilfe des Filters können wir den vorhandenen Status überprüfen:

checkList = (item) => {  // we can access this param and globals within filter
  var result = this.state.filter(value => value === item); // returns array of matching items

  result.length ? return `${item} exists` : this.setState({
    items: items.push(item) // bad practice, but to keep it light
  });
}
DBrown
quelle