Bagaimana cara mengirimkan parameter tambahan ke fungsi panggilan balik dalam metode Javascript .filter ()?

104

Saya ingin membandingkan setiap string dalam Array dengan string yang diberikan. Implementasi saya saat ini adalah:

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

Fungsi sederhana ini berfungsi, tetapi hanya karena saat ini wordToCompare disetel sebagai variabel global, tetapi tentu saja saya ingin menghindari ini dan meneruskannya sebagai parameter. Masalah saya adalah bahwa saya tidak yakin bagaimana mendefinisikan beginWith () sehingga menerima satu parameter tambahan, karena saya tidak benar-benar memahami bagaimana parameter default yang diperlukan diteruskan. Saya telah mencoba semua cara berbeda yang dapat saya pikirkan dan tidak ada yang berhasil.

Jika Anda juga dapat menjelaskan bagaimana parameter yang diteruskan ke fungsi panggilan balik 'built in' (maaf, saya tidak tahu istilah yang lebih baik untuk ini) akan bekerja dengan baik

agente_secreto
sumber

Jawaban:

152

Buat startsWithmenerima kata untuk dibandingkan dan mengembalikan fungsi yang kemudian akan digunakan sebagai fungsi filter / panggilan balik:

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

addressBook.filter(startsWith(wordToCompare));

Pilihan lain adalah menggunakan Function.prototype.bind [MDN] (hanya tersedia di browser yang mendukung ECMAScript 5, ikuti tautan untuk shim untuk browser lama) dan "perbaiki" argumen pertama:

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

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

Saya tidak begitu mengerti bagaimana parameter default yang dibutuhkan diteruskan

Tidak ada yang istimewa tentang itu. Pada titik tertentu, filtercukup panggil callback dan teruskan elemen array saat ini. Jadi itu adalah fungsi yang memanggil fungsi lain, dalam hal ini callback yang Anda berikan sebagai argumen.

Berikut adalah contoh fungsi serupa:

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;
}
Felix Kling
sumber
1
Ok sekarang saya mengerti. Saya mencoba untuk mengirimkan parameter langsung ke fungsi panggilan balik ... Saya benar-benar perlu bekerja pada JavaScript saya. Terima kasih Felix, jawaban Anda sangat membantu
agente_secreto
Bagaimana dengan menyampaikan argumen tambahan? Saya mencoba memberikan serangkaian argumen tetapi tampaknya gagal
geotheory
@geotheory: bagaimana dengan mereka? Anda memberikan beberapa argumen seperti fungsi lainnya.
Felix Kling
bind (ini) setelah nama fungsi bersama dengan rantai filter () membantu saya menggunakan. fungsi di dalam ini. Terima kasih.
Sagar Khatri
109

Parameter kedua dari filter akan mengatur ini di dalam callback.

arr.filter(callback[, thisArg])

Jadi Anda bisa melakukan sesuatu seperti:

function startsWith(element) {
    return element.indexOf(this) === 0;
}
addressBook.filter(startsWith, wordToCompare);
Jeff
sumber
7
Saya menemukan ini adalah jawaban terbaik.
Jeaf Gilbert
jadi sekarang array baru akan ditugaskan ke objek wordToCompare, bukan? Bagaimana cara mengakses larik baru nanti menggunakan objek wordToCompare?
Badhon Jain
jawaban Terbaik. berfungsi sempurna untuk filter dan pencarian. Dan sesuai dengan dokumentasi WC3 untuk keduanya: thisValue - Opsional. Nilai yang akan diteruskan ke fungsi untuk digunakan sebagai nilai "ini". Jika parameter ini kosong, nilai "tidak ditentukan" akan diteruskan sebagai nilai "ini"
richaa
1
@TarekEldeeb baru saja melewati objek yang Anda buat{one: 'haha', two:'hoho'}
toddmo
2
Ini adalah contoh yang bagus tentang bagaimana ada perbedaan besar di antara jawaban mengenai kompleksitas dan seberapa berbelit
belitnya
13

Bagi mereka yang mencari alternatif ES6 menggunakan fungsi panah, Anda dapat melakukan hal berikut.

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

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

Versi yang diperbarui menggunakan termasuk :

const startsWith = wordToCompare => (element, index, array) => {
  return element.includes(wordToCompare);
}
jhamPac.dll
sumber
Adakah cara untuk melewatkan parameter yang berbeda dari elemen, indeks, dan array? Misalnya, saya ingin meneruskan variabel X.
leandrotk
@leandrotk dalam hal ini "wordToCompare" adalah variabel "X" yang akan diteruskan.
GetBackerZ
11
function startsWith(element, wordToCompare) {
    return element.indexOf(wordToCompare) === 0;
}

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

addressBook.filter(function(element){
    return startsWith(element, word);
});
James Montagne
sumber
4

Anda dapat menggunakan fungsi panah di dalam filter, seperti ini:

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

Fungsi panah di MDN

Ekspresi fungsi panah memiliki sintaks yang lebih pendek dibandingkan dengan ekspresi fungsi dan secara leksikal mengikat nilai ini (tidak mengikat this, arguments, super, atau new.target miliknya sendiri). Fungsi panah selalu anonim. Ekspresi fungsi ini paling cocok untuk fungsi non-metode dan tidak dapat digunakan sebagai konstruktor.

oddRaven
sumber
Catatan: Tidak didukung di IE
Luis Lavieri
1

Bagi siapa pun yang bertanya-tanya mengapa fungsi panah lemak mereka diabaikan [, thisArg], misalnya mengapa

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

itu karena thisdi dalam fungsi panah tersebut terikat ketika fungsi dibuat dan disetel ke nilai thisdalam cakupan yang lebih luas, sehingga thisArgargumennya diabaikan. Saya menyiasatinya dengan cukup mudah dengan mendeklarasikan variabel baru dalam lingkup induk:

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

Berikut ini tautan ke beberapa bacaan lainnya: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this

JKettler
sumber
0

berdasarkan jawaban oddRaven dan https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

saya melakukannya dengan 2 cara berbeda. 1) menggunakan cara fungsi. 2) menggunakan cara inline.

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

Ashish
sumber
0

Ada cara mudah untuk menggunakan fungsi filter, mengakses semua parameter, dan tidak memperumitnya.

Kecuali callback thisArg disetel ke filter cakupan lain tidak membuat cakupannya sendiri, dan kita dapat mengakses params dalam cakupan saat ini. Kita dapat mengatur 'ini' untuk menentukan cakupan yang berbeda untuk mengakses nilai lain jika diperlukan, tetapi secara default diatur ke ruang lingkup asalnya. Anda dapat melihat ini digunakan untuk cakupan Angular di tumpukan ini .

Menggunakan indexOf mengalahkan tujuan filter, dan menambahkan lebih banyak overhead. Filter sudah melewati array, jadi mengapa kita perlu mengulanginya lagi? Sebagai gantinya, kita bisa menjadikannya fungsi murni sederhana .

Berikut adalah skenario use-case dalam metode kelas React dimana state memiliki array yang disebut items , dan dengan menggunakan filter kita dapat memeriksa state yang ada:

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