【问题标题】:Can someone please explain this regex filtering of an array有人可以解释一下这个数组的正则表达式过滤吗
【发布时间】:2013-05-31 22:48:04
【问题描述】:

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

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

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

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

【问题讨论】:

  • 如果你给我们变量key 那么是的。
  • @DavidStarkey 请看我的编辑。
  • 某人太聪明了。创建一个虚拟正则表达式 (/./) 只是为了访问 test 函数只是在炫耀。
  • @Dogbert RegExp.prototype.test.bind(new RegExp(key, "g"))

标签: javascript regex


【解决方案1】:

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

由于您从.test() 调用.bind(),因此您将获得.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"


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

演示: 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

【讨论】:

  • 感谢您提醒我们使其全球化。我所做的事情的结果有所帮助。
  • 当您说在第 4 个字符上继续搜索时,您是指数组中下一个元素的第 4 个字符,对吧?
  • @kjelelokk:正确。正则表达式对象记住最后一个匹配结束于索引2,因此如果再次使用相同的正则表达式对象进行另一次搜索,它将从索引3 开始。即使它正在搜索不同的字符串也是如此,这里就是这种情况。当它没有找到匹配项时,它会自行重置。仅供参考,您可以使用正则表达式对象的.lastIndex 查看索引是什么。您也可以手动将其重置为0。当然,如果您将其绑定为 this 而不持有对它的引用,则这是不可能的。
  • 感谢@CrazyTrain,关于正则表达式中全局标签的状态性的重要评论,我在其他任何地方都没有看到过该文档,但它可能会在过滤上下文中导致奇怪的副作用。跨度>
  • 感谢这个可爱的回答老兄。我不知道RegExp.prototype.test
【解决方案2】:

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

这就是为什么在你的例子中:

/./

生成一个空的正则表达式

/./.test

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

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

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

好像可以写的清楚很多:

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

【讨论】:

  • 我只能猜测作者太聪明了,不能再输入13个字符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-10
  • 1970-01-01
  • 2013-04-27
  • 2011-04-30
相关资源
最近更新 更多