Если на веб-страницу подключается множество скриптов, то может возникнуть проблема конфликта имен, если разные скрипты определяют переменные/константы и функции с одним и тем же именем. В ряде языков программирования можно сгруппировать функционал в отдельные блоки - "пространства имен" (как в 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