2011-10-13 12 views
82

Quiero comparar cada cadena en una matriz con una cadena dada. Mi implementación actual es:¿Cómo paso un parámetro adicional a la función de devolución de llamada en el método Javascript .filter()?

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

Esta función simple funciona, pero sólo porque ahora wordToCompare se está estableciendo como una variable global, pero por supuesto que quieren 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. Intenté todas las diferentes formas en que puedo pensar y ninguna de ellas funciona.

Si también podría explicar cómo los parámetros pasados ​​a incorporada una función de devolución de llamada (lo siento, no sé de un mejor término para estos) de trabajo que serían grandes

Respuesta

119

Hacer startsWith aceptar la palabra con el que comparar y devolver una función que luego se utiliza 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] (sólo disponible en Bro wser apoyo ECMAScript 5, siga el vínculo de una cuña para navegadores antiguos) y "fijar" el primer argumento:

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

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

Realmente no entiendo cómo se transmiten los parámetros por defecto que toma

No tiene nada de especial. En algún momento, filter solo llama a la devolución de llamada y pasa el elemento actual de la matriz. Entonces es una función que llama a otra función, en este caso la devolución de llamada pasa como argumento.

Aquí es 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; 
} 
+1

Ok ahora entiendo. Estaba intentando pasar los parámetros directamente a la función de devolución de llamada ... Realmente necesito trabajar en mi JavaScript. Gracias Félix, tu respuesta es muy útil –

+0

¿Qué tal si pasas argumentos adicionales? Intenté pasar una serie de argumentos, pero eso parece fallar – geotheory

+0

@geotheory: ¿qué hay de ellos? pasas argumentos múltiples como a cualquier otra función. –

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

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

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

El segundo parámetro de filtro establecerá este interior de la devolución de llamada.

arr.filter(callback[, thisArg]) 

Por lo que podría hacer algo como:

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

Esta respuesta debería ser la aceptada :) – DrLightman

+3

He encontrado que esta es la mejor respuesta. –

+0

así que ahora la nueva matriz se asignará al objeto wordToCompare, ¿verdad? ¿Cómo puede acceder a la nueva matriz más tarde utilizando el objeto wordToCompare? –

2

Puede utilizar la función de flecha dentro de un filtro, así:

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

Arrow functions on MDN

Una flecha expresión de función tiene una sintaxis más corta en comparación con la función expresa iones y léxicamente vincula el valor this (no se une a esto, argumentos, super o new.target). Las funciones de flecha son siempre anónimas. Estas expresiones de función son las más adecuadas para funciones que no son de método y no pueden usarse como constructores.

+0

Nota: No es compatible con IE –

0

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

lo hice de 2 maneras diferentes. 1) usando la forma 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) ;

3

Para aquellos que buscan una alternativa ES6 uso de las funciones de dirección, 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)); 
1

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

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

es porque this dentro de esas funciones de dirección están obligados cuando se crea la función y se establecen en el valor de this en el ámbito que abarca más amplia, por lo que el argumento thisArg se ignora. Tengo alrededor de este con bastante facilidad al declarar una nueva variable en un ámbito primario:

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

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

0

hay una manera fácil de utilizar la función de filtro , acceda a todos los parámetros y no lo complique.

A menos que la devolución de llamada de thisArg se establece en otro filtro de ámbito no crea su propio ámbito, y podemos acceder params dentro del ámbito actual. Podemos configurar 'esto' para definir un alcance diferente para acceder a otros valores si es necesario, pero de manera predeterminada se establece en el alcance desde el que se llama. Puede ver este que se utiliza para los ámbitos angulares in this stack.

El uso de indexOf está anulando el objetivo del filtro y agrega más sobrecarga. El filtro ya está pasando por la matriz, entonces, ¿por qué tenemos que repetirlo nuevamente? En su lugar, podemos hacer que sea un simple pure function.

He aquí un escenario de caso de uso en un método de la clase Reaccionar donde el estado tiene una matriz llamada artículos, y mediante el uso de filtro que puede comprobar 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 
    }); 
} 
Cuestiones relacionadas