Javascript .filter () yönteminde geri arama işlevine fazladan bir parametre nasıl iletebilirim?


106

Bir Dizideki her dizeyi belirli bir dizeyle karşılaştırmak istiyorum. Mevcut uygulamam:

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

Bu basit işlev işe yarıyor, ancak bunun tek nedeni şu anda wordToCompare'in global bir değişken olarak ayarlanması, ancak elbette bundan kaçınmak ve onu bir parametre olarak iletmek istiyorum. Benim sorunum, beginWith () 'i nasıl tanımlayacağımdan emin olmadığım için fazladan bir parametreyi kabul ediyor, çünkü aldığı varsayılan parametrelerin nasıl geçirildiğini gerçekten anlamıyorum. Düşünebildiğim tüm farklı yolları denedim ve hiçbiri işe yaramadı.

Ayrıca 'yerleşik' geri arama işlevlerine aktarılan parametrelerin (üzgünüm, bunlar için daha iyi bir terim bilmiyorum) nasıl çalıştığını da açıklayabilirseniz bu harika olurdu

Yanıtlar:


153

Make startsWithkarşı karşılaştırmak ve kelime kabul bir işlev döndürecek sonra filtre / geri arama fonksiyonu olarak kullanılacaktır:

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

addressBook.filter(startsWith(wordToCompare));

Diğer bir seçenek, Function.prototype.bind [MDN] kullanmaktır (yalnızca ECMAScript 5'i destekleyen tarayıcıda mevcuttur, eski tarayıcılar için bir dolguyu takip edin) ve ilk argümanı "düzeltin":

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

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

Alınan varsayılan parametrelerin nasıl geçirildiğini gerçekten anlamıyorum

Bunda özel bir şey yok. Bir noktada, filtersadece geri aramayı çağırır ve dizinin geçerli öğesini iletir. Dolayısıyla bu, başka bir işlevi çağıran bir işlev, bu durumda bağımsız değişken olarak ilettiğiniz geri arama.

İşte benzer bir fonksiyon örneği:

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
Tamam şimdi anladım. Parametreleri doğrudan geri arama işlevine aktarmaya çalışıyordum ... Gerçekten JavaScript'im üzerinde çalışmam gerekiyor. Teşekkürler Felix, cevabın çok yardımcı oldu
agente_secreto

Ek argümanlar iletmeye ne dersiniz? Bir dizi argümanı
iletmeyi

@geotheory: Peki ya onlar? diğer herhangi bir işleve benzer şekilde birden çok argüman iletirsiniz.
Felix Kling

bind (this) sonra function name ve filter () chaining bana .this inside function kullanmamda yardımcı oldu. Teşekkürler.
Sagar Khatri

109

Filtrenin ikinci parametresi bunu geri aramanın içinde ayarlayacaktır .

arr.filter(callback[, thisArg])

Böylece şöyle bir şey yapabilirsiniz:

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

7
Bunun en iyi cevap olduğunu buldum.
Jeaf Gilbert

yani şimdi yeni dizi wordToCompare nesnesine atanacak, değil mi? Yeni diziye daha sonra wordToCompare nesnesini kullanarak nasıl erişebilirim?
Badhon Jain

en iyi cevap. hem filtre hem de bul için mükemmel çalışır. Ve her ikisi için de WC3 başına dokümantasyon: thisValue - İsteğe bağlı. İşleve "bu" değeri olarak kullanılmak üzere iletilecek değer. Bu parametre boşsa, "tanımsız" değeri "bu" değeri olarak aktarılacaktır
richaa

1
@TarekEldeeb yaptığınız bir nesneyi {one: 'haha', two:'hoho'}
iletir

2
Bu, cevaplar arasında ne kadar büyük farklılıklar olabileceğinin ve ne kadar karmaşık olabileceğinin ve ne kadar basit olabileceğinin harika bir
örneğidir

14

Ok işlevlerini kullanarak bir ES6 alternatifi arayanlar için aşağıdakileri yapabilirsiniz.

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

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

Kullanılarak Güncelleme sürümü içerir :

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

Eleman, dizin ve diziden farklı bir parametre geçirmenin herhangi bir yolu var mı? Örneğin, bir X değişkeni geçirmek istiyorum.
leandrotk

@leandrotk bu durumda "wordToCompare", aktarılacak "X" değişkenidir.
GetBackerZ

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

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

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

4

Ok işlevini aşağıdaki gibi bir filtre içinde kullanabilirsiniz:

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

MDN'de ok fonksiyonları

Ok işlevi ifadesi, işlev ifadelerine kıyasla daha kısa bir sözdizimine sahiptir ve bu değeri sözcüksel olarak bağlar (kendi this, arguments, super veya new.target değerlerini bağlamaz). Ok işlevleri her zaman anonimdir. Bu işlev ifadeleri, yöntem dışı işlevler için en uygun olanıdır ve yapıcı olarak kullanılamazlar.


Not: IE'de desteklenmez
Luis Lavieri

1

Şişman ok işlevinin [, thisArg]neden görmezden geldiğini merak eden herkes için , örneğin neden

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

Bunun nedeni, thisbu ok işlevlerinin, işlev oluşturulduğunda bağlanması ve thisdaha geniş kapsayıcı kapsamda değerine ayarlanması , dolayısıyla thisArgargümanın yok sayılmasıdır. Bir üst kapsamda yeni bir değişken tanımlayarak bunu oldukça kolay bir şekilde çözdüm:

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

İşte biraz daha okumaya bir bağlantı: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this


0

oddRaven cevabına ve https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter temel alınarak

2 farklı şekilde yaptım. 1) işlev yolunu kullanarak. 2) satır içi şekilde kullanma.

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

Filtre işlevini kullanmanın, tüm parametrelere erişmenin ve onu fazla karmaşık hale getirmenin kolay bir yolu vardır.

Geri çağrının thisArg öğesi başka bir kapsam filtresine ayarlanmadıkça kendi kapsamını oluşturmaz ve mevcut kapsamdaki parametrelere erişebiliriz. Gerekirse diğer değerlere erişmek için farklı bir kapsam tanımlamak için 'this' ayarlayabiliriz, ancak varsayılan olarak çağrıldığı kapsama ayarlanır. Görebilirsiniz Bu Eğik kapsamları için kullanılan bu yığınında .

İndexOf'u kullanmak, filtreleme amacını ortadan kaldırır ve daha fazla ek yük getirir. Filtre zaten diziden geçiyor, öyleyse neden onu tekrar yinelememiz gerekiyor? Bunun yerine basit ve saf bir işlev yapabiliriz .

Durumun öğeler adında bir diziye sahip olduğu bir React sınıfı yöntemi içinde bir kullanım durumu senaryosu aşağıda verilmiştir ve filtre kullanarak mevcut durumu kontrol edebiliriz:

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
  });
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.