Pattern
(function (foo) {
...code...
foo.bar = baz;
...more code...
}(window.FOO = window.FOO || {});
У шаблона, который вы описываете, нет официального названия, потому что это три отдельных шаблона. Каждый паттерн имеет несколько названий, но в этом посте я буду использовать следующую терминологию:
- закрытие
- псевдоним
- расширение пространства имен
Закрытие
Основой всего узора является closure
. Это просто функция, которая используется для определения области видимости переменных и функций, чтобы они не загрязняли глобальное пространство имен:
No closure
//these declare window.foo and window.bar respectively
//as such, they pollute the global namespace
var foo;
function bar() {}
Closure, in this case, an Immediately Invoked Functional Expression (IIFE)
(function () {
//these declare foo and bar within the function
//but they are not accessible outside the function
var foo;
function bar() {}
}());
Преимущество хранения переменных внутри замыкания заключается в том, что вам не придется беспокоиться о том, что кто-то перезапишет используемые вами переменные. Это особенно важно для часто используемых временных переменных, таких как i
или j
.
Псевдоним
Второй важной частью этого шаблона является алиасинг. Псевдоним позволяет определить переменную и использовать ее внутри замыкания, не беспокоясь о том, в каком глобальном пространстве имен она находится.
Without Aliasing
(function () {
...
foo = window.SomeFunction(bar, baz);
...
}());
With Aliasing
(function (sf) { //local name
...
foo = sf(bar, baz);
...
}(window.SomeFunction)); //global namespace
Это особенно важно, поскольку это означает, что глобальное пространство имен можно изменить в большом файле JavaScript, изменив имя в одном месте. Это хорошая вещь. Кроме того, минификаторы могут сокращать внутренний псевдоним до однобуквенного имени переменной, такого как a
, что обеспечивает значительную экономию байтов при минимизации.
Расширение пространства имен
Шаблон расширения пространства имен основан на поведении объединения оператора или (||
). Во многих языках &&
и ||
возвращают либо true
, либо false
, но в JavaScript &&
возвращает первое значение falsey
(false
, 0
, ''
, null
, undefined
), а ||
возвращает первое значение truthy
(все, что не falsey
). Для обоих операторов, если соответствующий тип не найден, возвращается последний аргумент. Это делает оператор ||
удобным способом определения нового пространства имен, только если оно еще не существует.
Without namespace extension
if (typeof window.Foo === 'undefined') {
window.foo = {};
}
With namespace extension
window.foo = window.foo || {};
Это полезно, поскольку позволяет расширить пространство имен дополнительными свойствами и методами, не беспокоясь о том, в каком порядке были определены свойства и методы.
В этом первом примере FileA
нужно будет выполнить до FileB
:
FileA.js
window.foo = {};
window.foo.bar = 'baz';
FileB.js
window.foo.fizz = 'buzz';
Во втором примере File1
и File2
могут выполняться в любом порядке:
File1.js
window.foo = window.foo || {};
window.foo.bar = 'baz';
File2.js
window.foo = window.foo || {};
window.foo.fizz = 'buzz';
Все вместе сейчас
Использование каждого шаблона вместе создает очень мощный модульный скрипт:
//use foo internally so that you don't have to worry about
//what the global namespace is called
(function (foo) {
//declare variables internally that you want to keep local to the script
var i,
len,
internal,
qux;
//declare functions/properties on the alias when you want to expose them
foo.bar = function () {...};
//extend the global namespace so that existing extensions are persistent
}(window.FOO = window.FOO || {}));
person
zzzzBov
schedule
08.10.2012
FOO
. Это скроетwindow.FOO
, если вы явно не сошлетесь на него с помощьюwindow.FOO
. - person icktoofay   schedule 08.10.2012alert(window.FOO === foo); // true
Технического названия нет. Это зависит от его использования. Если вы предоставляете библиотеку, ссылайтесь на нее как на свою библиотеку. Если вы экспортируете конструкторFoo
, назовите его конструкторомFoo
. - person I Hate Lazy   schedule 08.10.2012window.FOO
в своем IIFE; Я всегда ссылался на егоAlias
(спасибо zzzzBov). Итак, использованиеFOO
сработало бы для меня. @pst Спасибо за ссылку! Извините, что я пропустил эту тему. @user1689607 user1689607 Спасибо за разъяснения, я очень ценю это! Спасибо всем за помощь... Я должен вам всем несколько пивоварен Орегона. :) - person mhulse   schedule 09.10.2012