【问题标题】:Backbone Collection filter methodBackbone Collection 过滤方法
【发布时间】:2013-05-15 04:13:15
【问题描述】:

有人能解释一下 Collection“类”中存在的 filter() 方法背后的机制吗?此方法的 Backbone API 似乎与以下示例实现不一致(取自 Todo 练习 @http://addyosmani.github.io/backbone-fundamentals/):

completed: function() {
    return this.filter(function( todo ) {
        return todo.get('completed');
    });
}

此代码 sn-p 生成一个模型对象数组,其“已完成”属性包含“真”。但是,我无法理解如何从这个函数返回一个对象数组

【问题讨论】:

    标签: javascript backbone.js collections filtering


    【解决方案1】:

    好奇心的关键在于源代码的下划线。您可能已经知道,Backbone.Collection 上可供您使用的大量方法都是从下划线引入的。

    让我们先看看他们是如何做到的:

    // Underscore methods that we want to implement on the Collection.
    // 90% of the core usefulness of Backbone Collections is actually implemented
    // right here:
    var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl',
    'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select',
    'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke',
    'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest',
    'tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle',
    'lastIndexOf', 'isEmpty', 'chain'];
    
    // Mix in each Underscore method as a proxy to `Collection#models`.
    _.each(methods, function(method) {
        Collection.prototype[method] = function() {
    
          // Important: BOLT ON THE COLLECTION MODELS TO THE ARGUMENTS.
          var args = slice.call(arguments);
          args.unshift(this.models);
    
          // .apply (since we have an array of arguments).
          return _[method].apply(_, args);
        };
    });
    

    所以我们有一个下划线方法名称列表。源代码循环遍历这些方法名称并将每个方法名称添加到您的集合原型中。重要提示:您会注意到此代码修补了参数列表以包含在您的集合模型中。

    现在看下划线的实际方法实现:

    _.filter = _.select = function(obj, iterator, context) {
      var results = [];
      if (obj == null) return results;
      if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
    
      each(obj, function(value, index, list) {
        if (iterator.call(context, value, index, list)) results.push(value);
      });
    
      return results;
    }
    

    您会注意到过滤器只是环绕每个对象并循环遍历传入的对象(属性)。主干版本所做的只是将此方法放入上下文中,以使您不必每次都传递模型。

    【讨论】:

      【解决方案2】:
      return todo.get('completed');
      

      基本上对应这个

      return todo.get('completed') === true ;
      

      所以集合整体属性completed中的所有todo Models设置为true都会从最里面的return语句返回

      而最外层的返回会返回过滤函数满足条件的所有模型的集合..

      这可以简单地写成

      completed: function() {
          var filteredModels =  this.filter(function( todo ) {
              return todo.get('completed');
          });
      
          return filteredModels;
      }
      

      【讨论】:

        【解决方案3】:

        Filter 方法为结果创建空数组并循环通过this.models。如果iterator 函数返回真实值,则模型被推送到结果数组。 在您的示例中,iterator

        function (todo) {
          return todo.get('completed');
        }
        

        iterator 返回一些经过真实检查的值

        // simplified call
        if (iterator()) results.push(value)
        

        【讨论】:

          【解决方案4】:

          这里的已完成函数是一个过滤函数,只显示已完成的待办事项

          因为主干在这里延伸下划线

          通常会调用 undescore 的过滤方法

          filter_.filter(list, iterator, [context]) Alias: select 
          

          查看列表中的每个值,返回一个包含所有通过真值测试(迭代器)的值的数组。委托给原生过滤器方法(如果存在)。

          意味着 todo.get 被传递到集合中的每个模型上,这是为了测试每个模型的完成状态,如果为真,则模型返回到函数的数组中

          【讨论】:

          • 请注意,您的回答应针对直接提出的具体问题;而不是简单地提供一个似乎可以满足提问者要求的代码块。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-11-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-01-14
          相关资源
          最近更新 更多