Какие преимущества делает использование (функция (окно, документ, undefined) {...}) (окно, документ)?

Я предполагаю, что использование этого шаблона - это новая жара, но я не понимаю, что это за преимущество, и я не понимаю его видимость.

Образец:

(function(window, document, undefined){
  window.MyObject = {
    methodA: function() { ... },
    methodB: function() { ... }
  };
})(window, document)

У меня есть несколько вопросов об этом.

Есть ли конкретное преимущество для инкапсуляции объекта, подобного этому?
Почему окна и документы подаются вместо обычного доступа?
Почему передается undefined?
Является ли прикрепление объекта, который мы создаем непосредственно к окну, особенно хорошая идея?

Я привык к тому, что я назову в стиле Crockford для инкапсуляции Javascript (потому что я получил его от видеороликов Douglas Crockford Javascript).

NameSpace.MyObject = function() {
  // Private methods
  // These methods are available in the closure
  // but are not exposed outside the object we'll be returning.
  var methodA = function() { ... };

  // Public methods
  // We return an object that uses our private functions,
  // but only exposes the interface we want to be available.
  return {

    methodB: function() {
      var a = methodA();
    },
    methodC: function() { ... }

  }
// Note that we're executing the function here.
}();

Является ли один из этих шаблонов функционально лучше другого? Является ли первая эволюцией другой?

Ответ 1

Почему для доступа к окну и документам вместо обычного доступа?

Как правило, чтобы закрепить процесс разрешения идентификатора, использование их в качестве локальных переменных может помочь (хотя IMO может улучшить производительность).

Передача глобального объекта также является широко используемым методом в нерабочих средах, где у вас нет идентификатора window в глобальной области видимости, например:

(function (global) {
  //..
})(this); // this on the global execution context is 
          // the global object itself

Почему передается undefined?

Это сделано потому, что глобальное свойство undefined в ECMAScript 3 является изменчивым, что означает, что кто-то может изменить его значение, влияющее на ваш код, например:

undefined = true; // mutable
(function (undefined) {
  alert(typeof undefined); // "undefined", the local identifier
})(); // <-- no value passed, undefined by default

Если вы внимательно посмотрите undefined на самом деле не передается (нет аргумента в вызове функции), это один из надежных способов получить значение undefined без использования свойства window.undefined.

Имя undefined в JavaScript не означает ничего особенного, это не ключевое слово, как true, false и т.д., это просто идентификатор.

Только для записи в ECMAScript 5 это свойство было сделано незаписываемым...

Является ли прикрепление объекта, который мы создаем непосредственно к окну, особенно хорошая идея?

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

Ответ 2

Этот особый стиль приносит определенные преимущества над стилем "Crockford". В первую очередь, передача window и document позволяет более эффективно минимизировать script. A minifier может переименовать эти параметры в односимвольные имена, сохраняя 5 и 7 байтов соответственно для каждой ссылки. Это может складываться: ссылки jQuery window 33 раза и document 91 раз. Минимизация каждого токена до одного символа сохраняет 802 байта.

Кроме того, вы получаете преимущество скорости выполнения. Когда я впервые прочитал утверждение @joekarl, что он дает преимущество в производительности, я подумал: "Это кажется довольно ложным". Таким образом, я профилировал фактическую производительность с помощью тестовой страницы. Ссылаясь на window сто миллионов раз, локальная ссылка на переменные обеспечивает скромное увеличение скорости на 20% (от 4200 мс до 3400 мс) в Firefox 3.6 и шокирующее увеличение на 31 000% (с 13 до 400 мс) в Chrome 9.

Конечно, вы никогда не будете ссылаться на window 100 000 000 раз на практике, и даже 10 000 прямых ссылок берут только 1 мс в Chrome, поэтому фактическое увеличение производительности здесь почти полностью пренебрежимо мало.

Почему передается undefined?

Потому что (как упоминалось @CMS) токен undefined на самом деле undefined. В отличие от null, он не имеет особого значения, и вы можете назначить этот идентификатор, как любое другое имя переменной. (Обратите внимание, однако, что это больше не соответствует true в ECMAScript 5.)

Является ли прикрепление объекта, который мы создаем непосредственно к окну, особенно хорошая идея?

Объект window - это глобальная область действия, так что именно то, что вы делаете в какой-то момент, независимо от того, вы или нет, явно написано "окно". window.Namespace = {}; и Namespace = {}; эквивалентны.

Ответ 3

Я с тобой использую стиль Крокфорда.

Чтобы ответить на ваши вопросы

1.Есть ли конкретное преимущество для инкапсуляции такого объекта?

Единственное преимущество, которое я вижу, заключается в создании локальных переменных окна и документа вместо глобальных переменных, вы получаете некоторую дополнительную безопасность, не имея возможности напрямую перезаписывать один из них, а также некоторое усиление производительности, поскольку оба они являются локальными.

2. Почему окна и документ подаются вместо обычного доступа?

. Локальные переменные, как правило, быстрее, но с jit-компиляцией в эти дни, которые становятся номинальными.

3.Что вы передаете undefined в?

Нет подсказки....

4. Прикрепляет ли мы объект, который мы создаем непосредственно к окну, особенно хорошая идея?

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

Ответ 4

Я думаю, что это в основном для кода, который нужно запускать в нескольких контекстах окна. Скажем, у вас сложное приложение с большим количеством фреймов и/или дочерних окон. Все они должны запускать код в MyObject, но вы хотите загрузить его только один раз. Таким образом, вы загружаете его в любом выбранном окне/кадре, но вы создаете MyObject для каждого окна/фрейма со ссылками на правильное окно и документ.

Взятие аргумента undefined пытается защитить от факта, что undefined можно изменить:

undefined = 3;
alert(undefined);

См. ответ CMS о том, как это повышает безопасность.