JavaScriptの.filter()メソッドでコールバック関数に追加のパラメーターを渡すにはどうすればよいですか?


104

配列内の各文字列を指定された文字列と比較したい。私の現在の実装は:

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

この単純な関数は機能しますが、現在wordToCompareがグローバル変数として設定されているためですが、もちろんこれを避けてパラメーターとして渡したいと思います。私の問題は、startsWith()の定義方法がわからないため、1つの追加パラメーターを受け入れることです。これは、取るデフォルトのパラメーターがどのように渡されるかがわからないためです。私は考えられるさまざまな方法をすべて試しましたが、どれも機能しません。

「ビルトイン」コールバック関数に渡されたパラメーター(申し訳ありませんが、これらの適切な用語はわかりません)がどのように機能するかについても説明できたら、すばらしいでしょう。

回答:


152

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

1
ああ、わかってるよ。パラメータをコールバック関数に直接渡そうとしていました... JavaScriptで作業する必要があります。Felixに感謝します。あなたの答えはとても役に立ちます
agente_secreto

追加の引数を渡すのはどうですか?引数の配列を渡そうとしましたが、失敗したようです
地質学的理論

@geotheory:それらはどうですか?他の関数と同じように複数の引数を渡します。
Felix Kling

関数名の後のbind(this)とfilter()チェーニングは、関数内で.thisを使用するのに役立ちました。ありがとう。
Sagar Khatri

108

filterの2番目のパラメーターは、これをコールバック内に設定します。

arr.filter(callback[, thisArg])

だからあなたは次のようなことをすることができます:

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

7
これが最良の答えだと思いました。
Jeaf Gilbert、2016

これで、新しい配列がwordToCompareオブジェクトに割り当てられますよね?後でwordToCompareオブジェクトを使用して新しい配列にアクセスするにはどうすればよいですか?
Badhon Jain

ベストアンサー。フィルターと検索の両方に最適です。そして、両方のWC3ドキュメンテーションごとです:thisValue-オプション。「this」値として使用される関数に渡される値。このパラメーターが空の場合、値「undefined」はその「this」値として渡されます
richaa

1
@TarekEldeebは作成したオブジェクトを渡すだけです{one: 'haha', two:'hoho'}
toddmo '24

2
これは、複雑さに関してどのように答えに大きな違いがあるか、そしてどれほど複雑であるか、どれほど簡単であるかについての良い例です
toddmo

13

矢印関数を使用して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);
}

要素、インデックス、配列から別のパラメーターを渡す方法はありますか?たとえば、X変数を渡します。
leandrotk

この場合@leandrotk「wordToCompareは」に渡される「X」変数である。
GetBackerZ

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

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

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

4

次のように、フィルター内で矢印関数を使用できます。

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

MDNの矢印関数

矢印関数式は、関数式に比べて構文が短く、字句的にthis値をバインドします(独自のthis、arguments、super、またはnew.targetをバインドしません)。アロー関数は常に匿名です。これらの関数式は、メソッド以外の関数に最適であり、コンストラクターとして使用できません。


注:IEではサポートされていません
Luis Lavieri、2017年

1

なぜファットアロー機能が無視されているのか疑問に思う人のために[, thisArg]、例えばなぜ

["DOG", "CAT", "DOG"].filter(animal => animal === this, "DOG") 戻り値 []

ためですthis関数が作成されるとの値に設定されている場合、それらの矢印機能がバインドされている内部のthis広い包括的な範囲で、そのthisArg引数は無視されます。親スコープで新しい変数を宣言することで、これをかなり簡単に回避できました。

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

ここにいくつかの詳細へのリンクがあります:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this


0

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


0

フィルター関数を使用し、すべてのパラメーターにアクセスし、過度に複雑にしない簡単な方法があります。

コールバックのthisArgが別のスコープに設定されていない限り、フィルターは独自のスコープを作成せず、現在のスコープ内のパラメーターにアクセスできます。必要に応じて他の値にアクセスするために、「this」を設定して別のスコープを定義できますが、デフォルトでは、呼び出し元のスコープに設定されています。あなたは見ることができ、これは角度のスコープのために使用され、このスタックに

indexOfを使用すると、フィルターの目的が無効になり、オーバーヘッドが増加します。フィルターは既に配列を通過しているので、なぜもう一度反復する必要があるのですか?代わりに、それを単純な純粋な関数にすることができます

以下に、Reactクラスメソッド内のユースケースシナリオを示します。ここでは、状態にitemsという配列があり、フィルターを使用して既存の状態を確認できます。

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
  });
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.