Как это underscore.js используйте это._wrapped

#javascript #underscore.js #each #wrapper

#javascript #underscore.js #каждый #оболочка

Вопрос:

Я читал аннотированный источник для Underscore.js и мне было интересно, как он используется this._wrapped при передаче объекта _() функции в отличие от обычного способа передачи объекта функции _ объекта.

Это:

 _(myObj).each(callback);
 

Против:

 _.each(myObj, callback);
 

Когда я запускаю первый вызов функции и приостанавливаю его в инструментах разработчика, в конечном итоге код заканчивается здесь:

 _.mixin = function(obj) {
  _.each(_.functions(obj), function(name) {
    var func = _[name] = obj[name];
    _.prototype[name] = function() {
      var args = [this._wrapped];
      push.apply(args, arguments);
      return result(this, func.apply(_, args));
    };
  });
};
 

Но я не уверен, как он узнал, что нужно туда идти. Может ли кто-нибудь помочь мне понять это? Кроме того, я пытался искать ответ раньше, но этот конкретный вопрос, похоже, никогда не возникал. Если на этот вопрос уже был дан ответ, приношу свои извинения.

Ответ №1:

Использование подчеркивания в объектно-ориентированном стиле:

 _([1, 2, 3]).map(function(n){ return n * 2; });
 

Вызывает создание экземпляра объекта:

 var _ = function(obj) {
  if (obj instanceof _) return obj;
  if (!(this instanceof _)) return new _(obj); // on this line
  this._wrapped = obj;
};
 

Волшебство, которое можно легко пропустить, заключается в отсутствии new ключевого слова, функция вызывается как любая другая функция (не как конструктор), this будет ссылаться на родительскую область (а не быть экземпляром _ ), поэтому запускает new оператор (и конструкцию объекта). Это очень умный способ избежать принудительного использования new .

Смотрите https://jsfiddle.net/336493L6 / чтобы увидеть этот паттерн в действии.

Все функции, статически используемые для объекта подчеркивания (each, map и т. Д.), Применяются к прототипу подчеркивания с помощью _.mixin функции.

Это строка, в которой это происходит:

 _.mixin(_);
 

Конечно, при отладке вы окажетесь в mixin функции, поскольку она оборачивает статические функции.

 _.prototype[name] = function() {
  var args = [this._wrapped];
  push.apply(args, arguments);
  return result(this, func.apply(_, args));
};
 

Эта прототипная версия статической функции вызовет статическую функцию с первым параметром, установленным this._wrapped равным . result в этом случае возвращаемое значение функции не изменится (оно используется для _.chain ).

Комментарии:

1. @Tomalak — вы неправильно прочитали, вторая строка проверяет !(this instanceof _) , что будет иметь место, если _() вызывается без new , однако, когда это выполняется, оно, в свою очередь, вызовет new _(obj) , который завершится ошибкой как первого, так и второго оператора if и достигнет 3-й строки.

2. Я обновил ответ с помощью JSFiddle, показывающего шаблон, о котором я говорю