Cómo paso un parámetro adicional a la función de devolución de llamada en Javascript.método filter ()?


Quiero comparar cada cadena en una Matriz con una cadena dada. Mi implementación actual es:

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

Esta simple función funciona, pero solo porque en este momento wordToCompare se está estableciendo como una variable global, pero por supuesto quiero evitar esto y pasarlo como un parámetro. Mi problema es que no estoy seguro de cómo definir startsWith () por lo que acepta un parámetro adicional, porque realmente no entiendo cómo se pasan los parámetros predeterminados que toma. Lo he intentado todo las diferentes formas en las que puedo pensar y ninguna de ellas funciona.

Si también pudiera explicar cómo funcionan los parámetros pasados a las funciones de devolución de llamada 'built in' (lo siento, no conozco un término mejor para estas), sería genial

Author: agente_secreto, 2011-10-13

8 answers

Haga que startsWith acepte la palabra con la que comparar y devuelva una función que luego se usará como función de filtro/devolución de llamada:

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

addressBook.filter(startsWith(wordToCompare));

Otra opción sería utilizar Function.prototype.bind [MDN] (solo disponible en navegadores compatibles con ECMAScript 5, siga un enlace para obtener una cuña para navegadores más antiguos) y" corrija " el primer argumento:

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

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

Realmente no entiendo cómo se pasan los parámetros predeterminados que toma

Hay no tiene nada de especial. En algún momento, filter simplemente llama a la devolución de llamada y pasa el elemento actual de la matriz. Por lo que es una función llamando a otra función, en este caso la devolución de llamada que pasa como argumento.

Aquí hay un ejemplo de una función similar:

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;
}
 126
Author: Felix Kling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-13 19:29:13

El segundo parámetro de filter establecerá este dentro de la devolución de llamada.

arr.filter(callback[, thisArg])

Así que podrías hacer algo como:

function startsWith(element) {
    return element.indexOf(this) === 0;
}
addressBook.filter(startsWith, wordToCompare);
 86
Author: Jeff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-02 17:51:41
function startsWith(element, wordToCompare) {
    return element.indexOf(wordToCompare) === 0;
}

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

addressBook.filter(function(element){
    return startsWith(element, word);
});
 10
Author: James Montagne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-13 19:14:44

Para aquellos que buscan una alternativa a ES6 usando funciones de flecha, puede hacer lo siguiente.

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

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

La versión actualizada usando incluye :

const startsWith = wordToCompare => (element, index, array) => {
  return element.includes(wordToCompare);
}
 4
Author: jhamPac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-09 01:41:26

Puede usar la función arrow dentro de un filtro, así:

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

Funciones de flecha en MDN

Una expresión de función arrow tiene una sintaxis más corta en comparación con las expresiones de función y enlaza léxicamente el valor this (no enlaza su propio this, arguments, super o new).objetivo). Las funciones de flecha son siempre anónimas. Estas expresiones de función son las más adecuadas para funciones no metodológicas y no se pueden utilizar como constructores.

 2
Author: oddRaven,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-11 20:18:17

Para cualquiera que se pregunte por qué su función de flecha gorda está ignorando [, thisArg], por ejemplo, por qué

["DOG", "CAT", "DOG"].filter(animal => animal === this, "DOG") devuelve []

Es porque this dentro de esas funciones de flecha están enlazadas cuando se crea la función y se establecen al valor de this en el ámbito abarcador más amplio, por lo que el argumento thisArg se ignora. Conseguí alrededor de esto bastante fácilmente declarando una nueva variable en un ámbito padre:

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

Aquí hay un enlace a algunas lecturas más: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this

 1
Author: Jimmy Kettler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-28 21:11:40

Basado en la respuesta de oddRaven y https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

Lo hice de 2 maneras diferentes . 1) usando la manera de la función . 2) usando la manera en línea .

//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) ;
 0
Author: Ashish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-15 18:09:16

Hay una manera fácil de usar la función de filtro, acceder a todos los parámetros, y no complicarlo demasiado.

A menos que la devolución de llamada thisArg esté establecida en otro filtro de ámbito no crea su propio ámbito, y podemos acceder a parámetros dentro del ámbito actual. Podemos establecer 'this' para definir un ámbito diferente con el fin de acceder a otros valores si es necesario, pero por defecto se establece en el ámbito desde el que se llama. Puede ver que se usa para alcances angulares en este stack .

Usar indexOf es derrotar el propósito del filtro y agregar más sobrecarga. Filtro ya está pasando por la matriz, así que ¿por qué necesitamos iterar a través de él de nuevo? En cambio, podemos hacer que sea una simple función pura.

Aquí hay un escenario de caso de uso dentro de un método de clase React donde el estado tiene un array llamado items , y usando filter podemos verificar el estado existente:

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
  });
}
 0
Author: DBrown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-24 17:18:51