有人可以解释这个数组的正则表达式过滤

时间:2013-05-31 14:27:21

标签: javascript regex

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

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

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

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

2 个答案:

答案 0 :(得分:15)

.bind()方法将返回一个函数,其中包含您作为第一个参数绑定的任何内容作为this的值。

由于您从.bind()致电.test(),因此您获得的.test()方法this绑定到new 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()回调,假设key"foo",则可以说一个val"foobar"。它将被允许通过过滤器。

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


以下是显示实际问题的具体示例:

DEMO: 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

答案 1 :(得分:6)

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

这就是你的例子中的原因:

/./

生成一个空的正则表达式

/./.test

是该正则表达式的测试方法

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

将该方法绑定到请求的方法,并返回一个执行test的新方法,其中this是基于key提供的正则表达式。

似乎可以写得更清楚:

RegExp.prototype.test.bind(new RegExp(key, 'g'))
相关问题