Как передать дополнительный параметр функции обратного вызова в Javascript.фильтр() метод?
Я хочу сравнить каждую строку в массив с заданной строкой. Моя текущая реализация:
function startsWith(element) {
return element.indexOf(wordToCompare) === 0;
}
addressBook.filter(startsWith);
эта простая функция работает, но только потому, что сейчас wordToCompare создается как глобальная переменная, но, конечно, я хочу избежать этого и передайте его в качестве параметра. Моя проблема заключается в том, что я не уверен, как определить startsWith () так что он принимает один дополнительный параметр, потому что я действительно не понимаю, как параметры по умолчанию он принимает пройденный. Я перепробовал все возможные способы, и ни один из них не работает.
Если бы вы также могли объяснить, как переданные параметры для "встроенных" функций обратного вызова (извините, я не знаю лучшего термина для них) работают, это было бы здорово
8 ответов:
сделать
startsWithпримите слово для сравнения и возвращает функция который затем будет использоваться в качестве фильтра / функции обратного вызова:function startsWith(wordToCompare) { return function(element) { return element.indexOf(wordToCompare) === 0; } } addressBook.filter(startsWith(wordToCompare));другой вариант - использовать
Function.prototype.bind[MDN] (доступно только в браузере, поддерживающем ECMAScript 5, перейдите по ссылке для прокладки для старых браузеров) и "исправьте" первый аргумент:function startsWith(wordToCompare, element) { return element.indexOf(wordToCompare) === 0; } addressBook.filter(startsWith.bind(this, wordToCompare));
Я действительно не понимаю, как по умолчанию параметры, которые он принимает, передаются
в этом нет ничего особенного. В какой-то момент
filterпросто вызывает обратный вызов и передает текущий элемент массива. Таким образом, это функция, вызывающая другую функцию, в этом случае обратный вызов вы передаете в качестве аргумента.вот пример подобной функции:
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; }
второй параметр фильтра будет установлен этой внутри обратного вызова.
arr.filter(callback[, thisArg])Так что вы могли бы сделать что-то вроде:
function startsWith(element) { return element.indexOf(this) === 0; } addressBook.filter(startsWith, wordToCompare);
function startsWith(element, wordToCompare) { return element.indexOf(wordToCompare) === 0; } // ... var word = "SOMETHING"; addressBook.filter(function(element){ return startsWith(element, word); });
для тех, кто ищет альтернативу ES6 с помощью функций стрелок, вы можете сделать следующее.
let startsWith = wordToCompare => (element, index, array) => { return element.indexOf(wordToCompare) === 0; } // where word would be your argument let result = addressBook.filter(startsWith("word"));обновленная версия с помощью включает в себя:
const startsWith = wordToCompare => (element, index, array) => { return element.includes(wordToCompare); }
вы можете использовать функцию стрелки внутри фильтра, как это:
result = addressBook.filter(element => element.indexOf(wordToCompare) === 0);выражение функции стрелки имеет более короткий синтаксис по сравнению с выражениями функции и лексически связывает это значение (не связывает его собственное this, arguments, super или new.цель.) Функции стрелки всегда анонимны. Эти выражения функций лучше всего подходят для не-методических функций, и они не могут быть использованы в качестве проектировщики.
для тех, кто задается вопросом, почему их функция жирной стрелки игнорирует
[, thisArg], Почему
["DOG", "CAT", "DOG"].filter(animal => animal === this, "DOG")возвращает[]потому что
thisвнутри этих стрелок функции привязываются при создании функции и устанавливаются в значениеthisв более широком контексте, охватывающем, поэтому
на основе ответа oddRaven и https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
Я сделал это 2 разных пути . 1) используя функцию пути . 2) используя встроенные пути .
//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) ;
существует простой способ использовать функцию фильтра, получить доступ ко всем параметрам и не усложнять ее.
если обратный вызов не thisArg установлен в другую область фильтр не создает свою собственную область, и мы можем получить доступ к парам в текущей области. Мы можем установить 'this' для определения другой области, чтобы получить доступ к другим значениям, если это необходимо, но по умолчанию он установлен в область, из которой он вызывается. Вы можете видеть этой используется для угловых областей в этом стеке.
использование indexOf побеждает цель фильтра и добавляет больше накладных расходов. Фильтр уже проходит через массив, так почему же нам нужно повторять его снова? Вместо этого мы можем сделать его простым чистая функция.
вот сценарий использования в методе класса React, где состояние имеет массив с именем предметы, и с помощью фильтра мы можем проверить существующие государства:
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 }); }
Comments