Если на веб-страницу подключается множество скриптов, то может возникнуть проблема конфликта имен, если разные скрипты определяют переменные/константы и функции с одним и тем же именем. В ряде языков программирования можно сгруппировать функционал в отдельные блоки - "пространства имен" (как в C#) или пакеты (как в Java). Разные пакеты/пространства имен могут определять переменные и функции с одинаковыми именами, но конфликта имен не будет. Однако в JavaScript не существует ни пакетов, ни пространств имен, но есть возможность эмулировать пространства имен с помощью специальной техники, которую еще называют паттерном "пространство имен".
Идея этого паттерна состоит в том, чтобы объединить связанные переменные/константы/функции в отдельный объект, который служит простым контейнером. Для обращения к переменным и функциям внутри подобного контейнера применяется его имя. И пока такие объекты-контейнеры имеют глобально уникальное имя, такой подход не приводит к каким-либо конфликтам имен. В качестве подобного эффекта это позволяет разгрузить глобальную область видимости, убрав из нее определения глобальных переменных и методов.
Например, рассмотрим следующий код:
// определяем объект-пространство имен
var MathLib = MathLib || {};
// определяем переменную внутри пространства имен
MathLib.MAX = 1234;
// определяем функцию внутри пространства имен
MathLib.sum = function(a, b) { return a + b;};
console.log(MathLib.sum(4, 5)); // 9
console.log(MathLib.MAX); // 1234
MathLib.MAX = 5678;
console.log(MathLib.MAX); // 5678
Здесь определяется пространство имен в виде объекта MathLib (условно говоря пространство имен MathLib). Обратите внимание на форму определения:
var MathLib = MathLib || {}
Данный паттерн предотвращает перезапись объекта MathLib, если он уже существует. Но при таком определении мы не можем использовать ключевые слова let
или const для определения объекта. Поэтому в данном случае объект определяется с помощью var.
Затем в MathLib для демонстрации определяются переменная MAX и функция sum, которые мы можем использовать, применяя имя объекта MathLib.
Можно сразу определить содержимое пространства имен:
var MathLib = MathLib || {
MAX: 1234,
sum: function(a, b) { return a + b;}
};
Таким образом, мы можем определять переменные и функции с одинаковыми именами внутри разных объектов-пространств имен, и у нас не возникнет конфликта имен:
var MathLib = MathLib || {
sum: function(a, b) { return a + b;}
};
var OtherMathLib = OtherMathLib || {
sum: function(nums) {
let result = 0;
for(n of nums) result += n;
return result;
}
};
console.log(MathLib.sum(4, 5)); // 9
console.log(OtherMathLib.sum([4, 5, 6])); // 15
В данном случае два объекта-пространства имен определяют функцию с одним и тем же именем sum, но разным функионалом. Но поскольку для доступа к функции применяется имя объекта, конфликта имен не будет.
Подобным образом можно определять вложенные пространства имен:
var Messages = Messages || {
ru: {
hello: "Привет",
bye: "Пока"
},
en: {
hello: "Hello",
bye: "Good bye"
},
};
console.log(Messages.ru.hello); // Привет
console.log(Messages.en.hello); // Hello