Hur skickar jag ett extra parameter till callback-funktionen i Javascript .filter()-metod?


Jag vill jämföra varje sträng i en array med en given sträng. Min nuvarande implementation är:

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

Denna enkla funktion fungerar, men bara för att wordToCompare just nu sätts som en global variabel, men självklart vill jag undvika detta och skicka det som en parameter. Mitt problem är att jag inte är säker på hur jag ska definiera startsWith() så att den accepterar en extra parameter, eftersom jag inte riktigt förstår hur de standardparametrar den tar skickas. Jag har försökt alla olika sätt jag kan komma på och ingen av dem fungerar.

Om du också kunde förklara hur de parametrar som skickas till 'inbyggda' återanropsfunktioner (ursäkta, jag känner inte till ett bättre uttryck för dessa) fungerar, vore det jättebra

Svar #1

Låt startsWith acceptera ordet att jämföra med och returnera en funktion som sedan kommer att användas som filter-/återanropfunktion:

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

addressBook.filter(startsWith(wordToCompare));

Ett annat alternativ skulle vara att använda Function.prototype.bind [MDN] (endast tillgängligt i webbläsare som stöder ECMAScript 5, följ en länk för en shim för äldre webbläsare) och "fästa" det första argumentet:

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

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

Jag förstår verkligen inte hur de standardparametrar som den tar vidarebefordras

Det är inget speciellt med det. Vid någon tidpunkt anropar filter bara callback-funktionen och skickar det aktuella elementet i arrayen. Så det är en funktion som anropar en annan funktion, i det här fallet callback-funktionen som du skickar som argument.

Här är ett exempel på en liknande 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;
}

Svar #2

Den andra parametern för filter kommer att sätta this inuti callbacken.

arr.filter(callback[, thisArg])

Så du kunde göra något som:

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

Svar #3

För de som letar efter ett ES6-alternativ med pilfunktioner kan du göra följande.

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

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

Uppdaterad version med inkluderar:

const startsWith = wordToCompare => (element, index, array) => {
  return element.includes(wordToCompare);
}

Svar #4

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

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

addressBook.filter(function(element){
    return startsWith(element, word);
});

Relaterade artiklar