8

我正在过滤一个数组,并在这里找到了一个正则表达式。我试图理解这一点:

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

但我不明白数组如何根据正则表达式测试它的值,或者为什么你必须从 /./ 开始而不是仅仅编写正则表达式。在这种情况下绑定如何工作?

编辑: Key 只是一个我想匹配的字符串,“hi”或“dog”或“anything really”。

4

2 回答 2

17

.bind()方法将返回一个函数,该函数将您作为第一个参数传递的任何值绑定为this.

由于您.bind()从调用.test(),因此您将获得绑定 to的.test()方法。thisnew RegExp(key, 'g')

/./这里无关紧要。这只是获得该方法的捷径RegExp.prototype.test

结果是您将有效地执行以下操作:

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

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

您应该注意到这有点危险,因为带有g修饰符的正则表达式对象是有状态的。这意味着它总是在前一个停止的地方开始一个新的搜索。

鉴于这种过滤场景,g似乎根本没有必要,而且实际上只会导致问题。

以下是使用此处的危险的示例g

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

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

所以在同一个字符串上调用同一个正则表达式会产生两个不同的结果。如果我们再次调用它,它将再次调用它true


因此,鉴于用作.filter()回调,假设keyis "foo",然后假设一个val is "foobar"。它将被允许通过过滤器。

但是让我们说下一个val"foobaz". 搜索将在第四个字符上继续,而不是从第一个字符开始,因此"foo"不会找到。


这是显示问题的具体示例:

演示:http: //jsfiddle.net/s9PzL/

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

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

所有的字符串都有"foo",所以它们都应该通过。但结果表明这不会发生。

document.body.textContent = result.join(", "); // foobar, foobuz
于 2013-05-31T14:34:15.300 回答
6

我认为这样做的原因是因为您想对数组中的每个项目执行测试方法。只是将测试方法传递给过滤器(可能)会弄乱方法的绑定。

这就是为什么在您的示例中:

/./

生成一个空的正则表达式

/./.test

是那个正则表达式的测试方法

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

将该方法绑定到请求的方法,并返回一个新方法,该方法执行testthis提供的基于key.

似乎可以写得更清楚:

RegExp.prototype.test.bind(new RegExp(key, 'g'))
于 2013-05-31T14:34:52.490 回答