program story

Javascript .filter () 메서드의 콜백 함수에 추가 매개 변수를 어떻게 전달합니까?

inputbox 2020. 8. 26. 07:50
반응형

Javascript .filter () 메서드의 콜백 함수에 추가 매개 변수를 어떻게 전달합니까?


배열의 각 문자열을 주어진 문자열과 비교하고 싶습니다. 내 현재 구현은 다음과 같습니다.

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

이 간단한 함수는 작동하지만 현재 wordToCompare 가 전역 변수로 설정되고 있기 때문에 가능 하지만 물론 이것을 피하고 매개 변수로 전달하고 싶습니다. 내 문제는 기본 매개 변수가 전달되는 방법을 실제로 이해하지 못하기 때문에 startsWith () 를 정의하는 방법을 잘 모르기 때문에 하나의 추가 매개 변수를 허용한다는 것입니다. 나는 내가 생각할 수있는 모든 다른 방법을 시도했지만 그들 중 어느 것도 작동하지 않습니다.

'내장'콜백 함수에 전달 된 매개 변수가 어떻게 작동하는지 설명 할 수 있다면 (죄송합니다.이 용어에 대한 더 나은 용어를 모르겠습니다.)


확인 startsWith에 대해 비교하고 말씀을 받아 들일 함수 반환 후 필터 / 콜백 함수로 사용됩니다 :

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

addressBook.filter(startsWith(wordToCompare));

또 다른 옵션은 Function.prototype.bind [MDN] (ECMAScript 5를 지원하는 브라우저에서만 사용 가능, 이전 브라우저의 경우 shim 링크를 따라 가십시오)을 사용하고 첫 번째 인수를 "수정"하는 것입니다.

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);
});

For those looking for an ES6 alternative using arrow functions, you can do the following.

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

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

Updated version using includes:

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

You can use the arrow function inside a filter, like this:

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

Arrow functions on MDN

An arrow function expression has a shorter syntax compared to function expressions and lexically binds the this value (does not bind its own this, arguments, super, or new.target). Arrow functions are always anonymous. These function expressions are best suited for non-method functions and they can not be used as constructors.


For anyone wondering why their fat arrow function is ignoring [, thisArg], e.g. why

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

it's because this inside those arrow functions are bound when the function is created and are set to the value of this in the broader encompassing scope, so the thisArg argument is ignored. I got around this pretty easily by declaring a new variable in a parent scope:

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

Here is a link to some more reading: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this


based on oddRaven answer and https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

i did it 2 different way . 1) using function way . 2) using inline way .

//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) ;


There is an easy way to use the filter function, access all params, and not over complicate it.

Unless the callback's thisArg is set to another scope filter does not create its own scope, and we can access params within the current scope. We can set 'this' to define a different scope in order to access other values if needed, but by default it is set to the scope it's called from. You can see this being used for Angular scopes in this stack.

Using indexOf is defeating the purpose of filter, and adding more overhead. Filter is already going through the array, so why do we need to iterate through it again? We can instead make it a simple pure function.

Here's a use-case scenario within a React class method where the state has an array called items, and by using filter we can check the existing state:

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
  });
}

참고URL : https://stackoverflow.com/questions/7759237/how-do-i-pass-an-extra-parameter-to-the-callback-function-in-javascript-filter

반응형