Метод фильтрации Backbone Collection

Может ли кто-нибудь объяснить механику метода filter(), который существует в «классе» Collection? Backbone API для этого метода выглядит несовместимым со следующим примером реализации (взято из упражнения Todo @ http://addyosmani.github.io/backbone-fundamentals/):

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

Этот фрагмент кода создает массив объектов модели, свойство «completed» которых содержит «true». Однако я не могу приблизиться к пониманию того, как массив объектов возвращается из этой функции.


person Albert Chang    schedule 15.05.2013    source источник


Ответы (4)


Ключ к вашему любопытству лежит в исходном коде с подчеркиванием. Как вы, вероятно, уже знаете, большое количество методов, доступных вам в 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;
}

Вы заметите, что фильтр просто обходит каждый и циклически проходит через переданный объект (свойства). Все, что делает базовая версия, — это помещает этот метод в контекст, чтобы избавить вас от необходимости каждый раз передавать модели.

person backdesk    schedule 12.12.2013

return todo.get('completed');

в основном соответствует этому

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

Таким образом, все todo Models в атрибуте коллекции completed, для которого задано значение true, будут возвращены из самого внутреннего оператора возврата.

И самый внешний возврат вернет коллекцию всех моделей, условие которых удовлетворяет функция фильтра.

Это можно просто записать как

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

    return filteredModels;
}
person Sushanth --    schedule 15.05.2013

Метод фильтра создает пустой массив для результатов и выполняет цикл по this.models. И если функция iterator возвращает истинное значение, модель помещается в массив результатов. В вашем примере iterator есть

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

iterator возвращает некоторое значение, которое проверяется на истинность

// simplified call
if (iterator()) results.push(value)
person Vitalii Petrychuk    schedule 15.05.2013

здесь завершенная функция — это функция фильтрации, отображающая только завершенную задачу

Поскольку магистраль расширяет подчеркивание здесь

вызывается отфильтрованный метод undescore, который обычно делает

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

Просматривает каждое значение в списке, возвращая массив всех значений, прошедших проверку на истинность (итератор). Делегаты собственного метода фильтра, если он существует.

Это означает, что todo.get передается каждой модели в коллекции, и это должно проверить каждую модель на предмет их завершенного состояния, если true, модель возвращается в массиве функции.

person Pascal    schedule 18.10.2013
comment
Обратите внимание, что ваши ответы должны относиться непосредственно к заданному конкретному вопросу; не просто предоставить блок кода, который, кажется, делает то, что хочет спрашивающий. - person Andrew Barber; 18.10.2013