2013-05-31 36 views
8

Tôi lọc một mảng và tìm thấy một regex tại đây. Tôi đang cố gắng để hiểu điều này:Ai đó có thể giải thích việc lọc regex này của một mảng

filterArray.filter(/./.test.bind(new RegExp(key, 'g'))) 

Nhưng tôi không hiểu tại sao các bài kiểm tra mảng nó đánh giá cao so với regex hoặc lý do tại sao bạn phải bắt đầu với /./ thay vì chỉ viết regex. Và làm thế nào để ràng buộc làm việc trong trường hợp này?

CHỈNH SỬA: Khóa chỉ là một chuỗi mà tôi muốn đối sánh, "chào" hoặc "chó" hoặc "bất kỳ thứ gì thực sự".

+2

Nếu bạn cung cấp cho chúng tôi biến 'key' sau đó có. –

+0

@DavidStarkey Vui lòng xem chỉnh sửa của tôi. – ptf

+0

Xem https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind –

Trả lời

14

Phương thức .bind() sẽ trả về một hàm với bất kỳ thứ gì bạn đã chuyển làm đối số đầu tiên được ràng buộc làm giá trị this.

Vì bạn đang gọi điện thoại .bind() từ .test(), bạn đang nhận được phương pháp .test() với this ràng buộc để new RegExp(key, 'g').

/./ không có liên quan ở đây. Nó chỉ là một cách ngắn để đến phương thức RegExp.prototype.test.

Kết quả là bạn sẽ có hiệu quả được thực hiện:

var regexp = new RegExp(key, 'g'); 

filterArray.filter(function(val) { 
    return regexp.test(val); 
}); 

Bạn nên lưu ý rằng đây là một chút nguy hiểm, bởi vì một đối tượng regex với modifier g là stateful. Điều này có nghĩa là nó luôn luôn bắt đầu một tìm kiếm mới, nơi tìm kiếm trước đó.

Với trường hợp lọc này, g dường như không cần thiết và có thể thực sự chỉ gây ra sự cố.

Dưới đây là một ví dụ về sự nguy hiểm của việc sử dụng các g đây:

var re = /./.test.bind(new RegExp("foo", 'g')); 
var str = "foobar"; 

console.log(re(str)); // true 
console.log(re(str)); // false 

Vì vậy, gọi regex như nhau trên cùng một chuỗi sản xuất hai kết quả khác nhau. Nếu chúng tôi gọi lại lần nữa, nó sẽ là true một lần nữa.


Vì vậy, cho việc sử dụng như một callback .filter(), chúng ta hãy nói key"foo", sau đó cho phép nói một val"foobar". Nó sẽ được cho phép thông qua bộ lọc.

Nhưng giả sử val tiếp theo là "foobaz". Tìm kiếm sẽ tiếp tục trên ký tự thứ tư thay vì bắt đầu từ ký tự thứ nhất, do đó, không thể tìm thấy "foo".


Dưới đây là ví dụ cụ thể cho thấy các vấn đề trong hành động:

DEMO:http://jsfiddle.net/s9PzL/

var filterArray = [ 
    "foobar", 
    "foobaz", 
    "foobuz", 
    "foobix" 
]; 

var result = filterArray.filter(/./.test.bind(new RegExp("foo", 'g'))); 

Tất cả các chuỗi có "foo", vì vậy tất cả họ sẽ nhận được thông qua. Nhưng kết quả cho thấy điều đó không xảy ra.

document.body.textContent = result.join(", "); // foobar, foobuz 
+0

Cảm ơn những người đứng đầu về làm cho nó toàn cầu. Và kết quả của những gì tôi đã làm một cách hiệu quả đã giúp. – ptf

+0

Bạn được chào đón. –

+0

Khi bạn nói tìm kiếm tiếp tục trên char thứ 4, bạn có nghĩa là char thứ 4 của phần tử tiếp theo trong mảng, phải không? – ptf

6

Tôi nghĩ lý do này được thực hiện theo cách này là vì bạn muốn thực thi phương pháp thử trên mỗi mục trong mảng. Chỉ cần vượt qua các phương pháp thử nghiệm để lọc sẽ (có lẽ) mess lên ràng buộc của phương pháp.

Đó là lý do tại sao trong ví dụ của bạn:

/./ 

Tạo một regex trống

/./.test 

là phương pháp thử nghiệm trên rằng regex

/./.test.bind(new Regex(..)) 

ràng buộc rằng phương pháp với phương pháp yêu cầu, và trả về một phương thức mới thực hiện test trong đó this là regex được cung cấp của bạn dựa trên key.

Có vẻ như rằng nó có thể đã được viết rất nhiều rõ ràng hơn:

RegExp.prototype.test.bind(new RegExp(key, 'g')) 
+0

Tôi chỉ có thể đoán rằng tác giả quá thông minh để nhập thêm 13 ký tự. – deerchao

+0

Thật vậy, anh ấy là :) –

Các vấn đề liên quan