Как работает этот синтаксис JavaScript/JQuery: (функция (окно, undefined) {}) (окно)?

Вы когда-нибудь смотрели под капотом в исходном коде JQuery 1.4 и замечали, как он инкапсулируется следующим образом:

(function( window, undefined ) {

  //All the JQuery code here 
  ...

})(window);

Я прочитал статью о JavaScript Namespacing, а другой - " Важная пара Parens," поэтому я знаю немного о том, что происходит здесь.

Но я никогда не видел этот синтаксис раньше. Что там делает undefined? И почему требуется window, а затем снова появится в конце?

Ответ 1

undefined является нормальной переменной и может быть изменен просто с помощью undefined = "new value";. Таким образом, jQuery создает локальную переменную "undefined", которая является ДЕЙСТВИТЕЛЬНО undefined.

Переменная окна создается локально по соображениям производительности. Потому что, когда JavaScript просматривает переменную, она сначала переходит через локальные переменные, пока не найдет имя переменной. Когда он не найден, JavaScript переходит через следующую область и т.д., Пока он не фильтрует глобальные переменные. Поэтому, если переменная окна сделана локальной, JavaScript может быстрее ее искать. Дополнительная информация: Ускорить свой JavaScript - Николас К. Закас

Ответ 2

Undefined

Объявляя undefined как аргумент, но никогда не передавая ему значение, он гарантирует, что он всегда undefined, так как это просто переменная в глобальной области, которая может быть перезаписана. Это делает a === undefined безопасной альтернативой typeof a == 'undefined', которая сохраняет несколько символов. Он также делает код более minifier дружественным, так как undefined можно сократить до u, например, сохранив еще несколько символов.

Window

Передача window в качестве аргумента хранит копию в локальной области, что влияет на производительность: http://jsperf.com/short-scope. Все обращения к window теперь должны перемещаться на один уровень за пределы цепочки областей. Как и в случае с undefined, локальная копия снова позволяет более агрессивную оценку.


Sidenote:

Хотя это, возможно, и не было целью разработчиков jQuery, передача в window позволяет более легко интегрировать библиотеку в средах Javascript на стороне сервера, например node.js - где нет глобального объекта window. В такой ситуации нужно заменить только одну строку, чтобы заменить объект window на другой. В случае jQuery может быть создан и передан объект mock window с целью очистки HTML (библиотека, такая как jsdom может это сделать).

Ответ 3

Другие объяснили undefined. undefined - это как глобальная переменная, которая может быть переопределена для любого значения. Этот метод заключается в том, чтобы предотвратить проверку всех ошибок undefined, если кто-то написал, undefined = 10 где-то. Аргумент, который никогда не передается, гарантированно будет реальным undefined независимо от значения переменной undefined.

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

(function() {
   console.log(window);
   ...
   ...
   ...
   var window = 10;
})();

Что делает консольный журнал? Правильно ли значение объекта window? Неправильно! 10? Неправильно! Он регистрирует undefined. Javascript-интерпретатор (или JIT-компилятор) переписывает его таким образом -

(function() {
   var window; //and every other var in this function

   console.log(window);
   ...
   ...
   ...
   window = 10;

})();

Однако, если вы получаете переменную window в качестве аргумента, нет никакого var и, следовательно, никаких сюрпризов.

Я не знаю, делает ли это jQuery, но если вы переопределяете локальную переменную window в любой точке вашей функции по какой-либо причине, неплохо заимствовать ее из глобальной области.

Ответ 4

window передается так же, как только кто-то решит переопределить оконный объект в IE, я предполагаю, что тот же для undefined, если он будет повторно назначен каким-либо образом позже.

Верхний window в том, что script просто называет аргумент "окно", аргумент, который более локален, чем глобальная ссылка window, и это то, что будет использовать код внутри этого закрытия. window в конце на самом деле указывает, что передать для первого аргумента, в этом случае текущее значение window... надеюсь, что вы еще не напортачили window, прежде чем это произойдет.

Об этом может быть проще подумать, показав наиболее типичный случай, используемый в jQuery, плагине .noConflict(), поэтому для большинства кода, вы все равно можете использовать $, даже если это означает что-то отличное от jQuery вне этой области:

(function($) {
  //inside here, $ == jQuery, it was passed as the first argument
})(jQuery);

Ответ 5

Протестировано с 1000000 итерациями. Такая локализация не влияла на производительность. Даже ни одна миллисекунда в 1000000 итераций. Это просто бесполезно.