ฉันจะส่งพารามิเตอร์พิเศษไปยังฟังก์ชันการเรียกกลับในวิธี Javascript .filter () ได้อย่างไร


107

ฉันต้องการเปรียบเทียบแต่ละสตริงใน Array กับสตริงที่กำหนด การใช้งานปัจจุบันของฉันคือ:

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

ฟังก์ชันง่ายๆนี้ใช้งานได้ แต่เนื่องจากตอนนี้wordToCompareถูกตั้งค่าเป็นตัวแปรส่วนกลาง แต่แน่นอนว่าฉันต้องการหลีกเลี่ยงสิ่งนี้และส่งผ่านเป็นพารามิเตอร์ ปัญหาของฉันคือฉันไม่แน่ใจว่าจะกำหนดstartWith () อย่างไรดังนั้นจึงยอมรับพารามิเตอร์พิเศษหนึ่งตัวเนื่องจากฉันไม่เข้าใจจริงๆว่าพารามิเตอร์เริ่มต้นจะส่งผ่านอย่างไร ฉันได้ลองวิธีต่างๆทั้งหมดที่ฉันคิดได้และไม่มีวิธีใดได้ผล

หากคุณสามารถอธิบายได้ว่าพารามิเตอร์ที่ส่งผ่านไปยังฟังก์ชันการโทรกลับ 'ในตัว' (ขออภัยฉันไม่รู้คำศัพท์ที่ดีกว่าสำหรับสิ่งเหล่านี้) ทำงานได้ดีเพียงใด

คำตอบ:


153

ให้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;
}

1
โอเคตอนนี้ฉันเข้าใจแล้ว. ฉันพยายามส่งผ่านพารามิเตอร์ไปยังฟังก์ชันเรียกกลับโดยตรง ... ฉันต้องทำงานกับ JavaScript ของฉันจริงๆ ขอบคุณเฟลิกซ์คำตอบของคุณมีประโยชน์มาก
agente_secreto

สิ่งที่เกี่ยวกับการส่งข้อโต้แย้งเพิ่มเติม? ฉันพยายามส่งอาร์กิวเมนต์ แต่ดูเหมือนจะล้มเหลว
geotheory

@geotheory: แล้วพวกเขาล่ะ? คุณส่งผ่านหลายอาร์กิวเมนต์เช่นเดียวกับฟังก์ชันอื่น ๆ
Felix Kling

ผูก (สิ่งนี้) หลังชื่อฟังก์ชันพร้อมกับตัวกรอง () การผูกมัดช่วยให้ฉันใช้ฟังก์ชันภายในนี้ ขอบคุณ.
Sagar Khatri

110

พารามิเตอร์ที่สองของตัวกรองจะตั้งค่านี้ภายในการเรียกกลับ

arr.filter(callback[, thisArg])

คุณสามารถทำสิ่งต่างๆเช่น:

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

7
ฉันพบว่านี่คือคำตอบที่ดีที่สุด
Jeaf Gilbert

ดังนั้นอาร์เรย์ใหม่จะถูกกำหนดให้กับวัตถุ wordToCompare ใช่ไหม? สามารถเข้าถึงอาร์เรย์ใหม่ในภายหลังโดยใช้วัตถุ wordToCompare ได้อย่างไร
Badhon Jain

คำตอบที่ดีที่สุด ทำงานได้อย่างสมบูรณ์แบบสำหรับทั้งตัวกรองและการค้นหา และเป็นไปตามเอกสาร WC3 สำหรับทั้งสอง: thisValue - ไม่บังคับ ค่าที่จะส่งผ่านไปยังฟังก์ชันเพื่อใช้เป็นค่า "this" หากพารามิเตอร์นี้ว่างเปล่าค่า "ไม่ได้กำหนด" จะถูกส่งผ่านเป็นค่า "this"
richaa

1
@TarekEldeeb เพียงแค่ส่งวัตถุที่คุณทำ{one: 'haha', two:'hoho'}
Toddmo

2
นี่เป็นตัวอย่างที่ดีว่าคำตอบมีความแตกต่างกันอย่างมากมายเกี่ยวกับความซับซ้อนและความซับซ้อนของคำตอบนั้นจะเป็นอย่างไรเทียบกับความเรียบง่ายเพียงใด
Toddmo

14

สำหรับผู้ที่มองหาทางเลือก 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


4

คุณสามารถใช้ฟังก์ชันลูกศรภายในตัวกรองได้ดังนี้:

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

ฟังก์ชั่นลูกศรบน MDN

นิพจน์ฟังก์ชันลูกศรมีไวยากรณ์ที่สั้นกว่าเมื่อเทียบกับนิพจน์ฟังก์ชันและผูกค่านี้เป็นคำศัพท์ (ไม่ผูกสิ่งนี้อาร์กิวเมนต์ super หรือ new.target ของตัวเอง) ฟังก์ชันลูกศรจะไม่ระบุชื่อเสมอ นิพจน์ฟังก์ชันเหล่านี้เหมาะที่สุดสำหรับฟังก์ชันที่ไม่ใช่วิธีการและไม่สามารถใช้เป็นตัวสร้างได้


หมายเหตุ: ไม่รองรับ IE
Luis Lavieri

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ของ callback ถูกตั้งค่าเป็นตัวกรองขอบเขตอื่นไม่ได้สร้างขอบเขตของตัวเองและเราสามารถเข้าถึงพารามิเตอร์ภายในขอบเขตปัจจุบันได้ เราสามารถตั้งค่า 'this' เพื่อกำหนดขอบเขตที่แตกต่างกันเพื่อเข้าถึงค่าอื่น ๆ หากจำเป็น แต่โดยค่าเริ่มต้นจะถูกกำหนดเป็นขอบเขตที่เรียกใช้ คุณสามารถเห็นสิ่งนี้ใช้สำหรับขอบเขตเชิงมุมในสแต็กนี้

การใช้ indexOf กำลังเอาชนะวัตถุประสงค์ของตัวกรองและเพิ่มค่าโสหุ้ยเพิ่มเติม ตัวกรองกำลังผ่านอาร์เรย์อยู่แล้วทำไมเราต้องวนซ้ำอีกครั้ง เราสามารถทำให้มันเป็นฟังก์ชันบริสุทธิ์ธรรมดา ๆแทนได้

นี่คือสถานการณ์การใช้งานภายในเมธอดคลาส React ที่สถานะมีอาร์เรย์ที่เรียกว่ารายการและโดยใช้ตัวกรองเราสามารถตรวจสอบสถานะที่มีอยู่:

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.