Làm cách nào để chuyển một tham số bổ sung cho hàm gọi lại trong phương thức .filter () của Javascript?


104

Tôi muốn so sánh từng chuỗi trong Mảng với một chuỗi đã cho. Cách triển khai hiện tại của tôi là:

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

Hàm đơn giản này hoạt động, nhưng chỉ vì ngay bây giờ wordToCompare đang được đặt làm biến toàn cục, nhưng tất nhiên tôi muốn tránh điều này và chuyển nó dưới dạng tham số. Vấn đề của tôi là tôi không chắc chắn cách định nghĩa startWith () để nó chấp nhận một tham số bổ sung, bởi vì tôi không thực sự hiểu cách các tham số mặc định mà nó nhận được truyền. Tôi đã thử tất cả các cách khác nhau mà tôi có thể nghĩ ra và không có cách nào trong số đó hiệu quả.

Nếu bạn cũng có thể giải thích cách các tham số được truyền cho các hàm gọi lại 'tích hợp sẵn' (xin lỗi, tôi không biết thuật ngữ nào tốt hơn cho các hàm này) hoạt động tốt

Câu trả lời:


152

Thực hiện startsWithchấp nhận từ để so sánh và trả về một hàm sau đó sẽ được sử dụng làm hàm lọc / gọi lại:

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

addressBook.filter(startsWith(wordToCompare));

Một tùy chọn khác sẽ là sử dụng Function.prototype.bind [MDN] (chỉ khả dụng trong trình duyệt hỗ trợ ECMAScript 5, hãy nhấp vào liên kết để có miếng đệm cho các trình duyệt cũ hơn) và "sửa" đối số đầu tiên:

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

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

Tôi không thực sự hiểu cách truyền các tham số mặc định mà nó cần

Không có gì đặc biệt về nó. Tại một số điểm, filterchỉ cần gọi lệnh gọi lại và chuyển phần tử hiện tại của mảng. Vì vậy, đó là một hàm gọi một hàm khác, trong trường hợp này là lệnh gọi lại mà bạn chuyển làm đối số.

Đây là một ví dụ về một chức năng tương tự:

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
Ừ bây giờ tôi hiểu rồi. Tôi đang cố gắng truyền trực tiếp các tham số tới hàm gọi lại ... Tôi thực sự cần làm việc trên JavaScript của mình. Cảm ơn bạn Felix, câu trả lời của bạn là rất hữu ích
agente_secreto

Điều gì về việc chuyển các đối số bổ sung? Tôi đã thử truyền một loạt các đối số nhưng điều đó dường như không thành công
geotheory

@geotheory: còn họ thì sao? bạn truyền nhiều đối số như bất kỳ hàm nào khác.
Felix Kling

bind (this) sau tên hàm cùng với chuỗi filter () đã giúp tôi sử dụng hàm .this bên trong. Cảm ơn.
Sagar Khatri

108

Tham số thứ hai của bộ lọc sẽ đặt giá trị này bên trong lệnh gọi lại.

arr.filter(callback[, thisArg])

Vì vậy, bạn có thể làm điều gì đó như:

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

7
Tôi thấy đây là câu trả lời tốt nhất.
Jeaf Gilbert

vậy bây giờ mảng mới sẽ được gán cho đối tượng wordToCompare đúng không? Làm cách nào để truy cập vào mảng mới sau này bằng cách sử dụng đối tượng wordToCompare?
Badhon Jain

câu trả lời tốt nhất. hoạt động hoàn hảo cho cả bộ lọc và tìm kiếm. Và theo tài liệu WC3 cho cả hai: thisValue - Tùy chọn. Giá trị được chuyển cho hàm sẽ được sử dụng làm giá trị "this" của nó. Nếu tham số này là trống rỗng, giá trị "không xác định" sẽ được thông qua như "này" của nó giá trị
richaa

1
@TarekEldeeb chỉ cần vượt qua một đối tượng bạn thực hiện{one: 'haha', two:'hoho'}
toddmo

2
Đây là một ví dụ tuyệt vời về cách có thể có sự khác biệt lớn giữa các câu trả lời như tính phức tạp và làm thế nào họ có thể phức tạp vs cách đơn giản họ có thể
toddmo

13

Đối với những người đang tìm kiếm một giải pháp thay thế ES6 bằng cách sử dụng các hàm mũi tên, bạn có thể làm như sau.

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

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

Phiên bản cập nhật sử dụng bao gồm :

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

Có cách nào để truyền một tham số khác từ phần tử, chỉ mục và mảng không? Ví dụ, tôi muốn truyền một biến X.
leandrotk

@leandrotk trong trường hợp này "wordToCompare" là biến "X" được chuyển vào.
GetBackerZ

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

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

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

4

Bạn có thể sử dụng chức năng mũi tên bên trong bộ lọc, như sau:

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

Các hàm mũi tên trên MDN

Biểu thức hàm mũi tên có cú pháp ngắn hơn so với biểu thức hàm và liên kết từ vựng với giá trị this (không ràng buộc giá trị this, đối số, super hoặc new.target của riêng nó). Hàm mũi tên luôn ẩn danh. Các biểu thức hàm này phù hợp nhất cho các hàm không phải là phương thức và chúng không thể được sử dụng làm hàm tạo.


Lưu ý: Không được hỗ trợ trên IE
Luis Lavieri

1

Đối với bất kỳ ai thắc mắc tại sao chức năng mũi tên béo của họ bị bỏ qua [, thisArg], ví dụ: tại sao

["DOG", "CAT", "DOG"].filter(animal => animal === this, "DOG") trả lại []

đó là bởi vì thisbên trong các hàm mũi tên đó bị ràng buộc khi hàm được tạo và được đặt thành giá trị thistrong phạm vi bao trùm rộng hơn, nên thisArgđối số bị bỏ qua. Tôi đã giải quyết vấn đề này khá dễ dàng bằng cách khai báo một biến mới trong phạm vi cha:

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

Đây là liên kết đến một số bài đọc khác: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this


0

dựa trên câu trả lời retailRaven và https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

tôi đã làm nó theo 2 cách khác nhau. 1) sử dụng cách chức năng. 2) bằng cách sử dụng nội tuyến.

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

Có một cách dễ dàng để sử dụng chức năng bộ lọc, truy cập tất cả các tham số và không quá phức tạp hóa nó.

Trừ khi thisArg của callback được đặt thành một bộ lọc phạm vi khác không tạo phạm vi riêng của nó và chúng ta có thể truy cập các tham số trong phạm vi hiện tại. Chúng tôi có thể đặt 'this' để xác định một phạm vi khác để truy cập các giá trị khác nếu cần, nhưng theo mặc định, nó được đặt thành phạm vi được gọi từ đó. Bạn có thể thấy điều này được sử dụng cho phạm vi Angular trong ngăn xếp này .

Sử dụng indexOf đang đánh bại mục đích của bộ lọc và tăng thêm chi phí. Bộ lọc đã đi qua mảng, vậy tại sao chúng ta cần lặp lại nó một lần nữa? Thay vào đó chúng ta có thể biến nó thành một hàm thuần túy đơn giản .

Đây là một tình huống sử dụng trong một phương thức lớp React trong đó trạng thái có một mảng được gọi là các mục và bằng cách sử dụng bộ lọc, chúng ta có thể kiểm tra trạng thái hiện có:

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
  });
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.