underscore.js过滤函数

3

我正在尝试学习backbone.js和(顺带)underscore.js,但是我有些难以理解一些惯例。在编写一个简单的搜索过滤器时,我认为以下内容会起作用:

var search_string = new RegExp(query, "i");

        var results = _.filter(this, function(data){
            return search_string.test(data.get("title"));
        }));

但是,事实上,为了使其正常工作,我需要将我的过滤函数更改为以下内容:

var search_string = new RegExp(query, "i");

        var results = _(this.filter(function(data){
            return search_string.test(data.get("title"));
        }));

基本上,我想了解为什么第二个例子可以工作,而第一个不能。根据文档 (http://documentcloud.github.com/underscore/#filter) ,我认为前者应该可以工作。或者这只是我旧的 jQuery 习惯... 有人能为我解释一下吗?


应该是 _.filter -- 抱歉那是个打字错误。使用 _.filter 时,数据为空,因此 "results" 返回一个空数组。 - bento
这是一个 Backbone 集合吗? - mu is too short
是的,没错。console.log(this)会给我提供一个带有长度、模型等属性的“子级”。 - bento
2个回答

4

我猜测你正在使用一个带有本地 Array#filter 实现的浏览器。在控制台中尝试这些代码并查看结果:

[].filter.call({ a: 'b' }, function(x) { console.log(x) });
[].filter.call([1, 2],     function(x) { console.log(x) });

第一个不会做任何事情,第二个将输出12http://jsfiddle.net/ambiguous/tkRQ3/)。问题不在于data为空,而是原生的Array#filter不知道如何应用于非数组对象。
所有Underscore的方法(包括filter)都会使用本地实现(如果可用):

如果存在,则委托给本机filter方法。

因此,除非您使用不提供本地实现的浏览器,否则 Array-ish Underscore 方法通常不会像 _.m(collection, ...)那样工作。
Backbone 集合是数组模型的包装器,模型数组位于c.models中,因此您需要:
_.filter(this.models, function(data) { ... });

Backbone混合了一些Underscore方法:

Backbone代理到Underscore.js,在Backbone.Collection上提供了28个迭代函数。

其中之一是filter。这些代理将Underscore方法应用于集合的模型数组,因此c.filter(...)_.filter(c.models, ...)相同。

这种混合可能会让Underscore正在进行的"我应该使用本机方法"检查变得混乱:

if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);

你可以在普通对象上使用_.filter_.filter({a:'b'}, ...))并获得合理的结果,但是当你在集合上使用_.filter(backbone_collection, ...)时会失败,因为集合已经有了Underscore方法。
这里有一个简单的演示,希望能澄清问题:http://jsfiddle.net/ambiguous/FHd3Y/1/

-1
出于与$('#element')可以工作而$#element不能的同样原因。_是下划线对象的全局变量,就像$jQuery对象的全局变量一样。 _()表示查找_对象。_filter表示查找名为_filter的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接