Есть ли “краткий” способ создать пространство имен в JavaScript?
-
08-06-2019 - |
Вопрос
Я часто сталкивался с сайтами, которые помещают весь свой JavaScript внутрь namespace
структура по линиям:
namespaces = { com : { example: { example.com's data} }
Однако безопасная настройка этого по отношению к другим фреймворкам с пространством имен, по-видимому, требует относительно большого объема кода (определяется как > 2 строк).Мне было интересно, знает ли кто-нибудь краткий способ сделать это?Кроме того, существует ли относительно стандартный / непротиворечивый способ его структурирования?Например, является ли com
пространство имен напрямую подключено к глобальному объекту или оно подключено через объект пространства имен?
[Править:упс, очевидно {com = { ... } }
не получилось бы ничего близкого к тому, что я задумал, спасибо Shog9 за указание на это.]
Решение
Javascript не имеет автономных пространств имен.В нем есть функции, которые могут предоставить область для разрешения имен, и объекты, которые могут вносить вклад в именованные данные, доступные в данной области.
Вот ваш пример, исправленный:
var namespaces = { com: { example: { /* example.com's data */ } } }
Это переменная namespaces
присваивается объектный литерал.Объект содержит одно свойство: com
, объект с одним свойством: example
, объект, который предположительно содержал бы что-то интересное.
Итак, вы можете ввести что-то вроде пространства имен.com.example.Какое- то свойство или функция в качестве примера и все это сработает.Конечно, это тоже нелепо.У вас нет иерархического пространства имен, у вас есть объект, содержащий объект, содержащий объект с вещами, которые вам действительно небезразличны.
var com_example_data = { /* example.com's data */ };
Это работает так же хорошо, без бессмысленной иерархии.
Сейчас, если вы на самом деле хотеть чтобы построить иерархию, вы можете попробовать что-то вроде этого:
com_example = com_example || {};
com_example.flags = com_example.flags || { active: false, restricted: true};
com_example.ops = com_example.ops || (function()
{
var launchCodes = "38925491753824"; // hidden / private
return {
activate: function() { /* ... */ },
destroyTheWorld: function() { /* ... */ }
};
})();
...который, ИМХО, достаточно лаконичен.
Другие советы
Вот интересная статья Питера Мишо о Пространство имен Javascript.Он обсуждает 3 различных типа пространства имен Javascript:
- Пространство имен с префиксом
- Пространство имен одного объекта
- Пространство имен вложенных объектов
Я не буду заниматься плагиатом того, что он здесь сказал, но я думаю, что его статья очень информативна.
Питер даже зашел так далеко, что указал на то, что у некоторых из них есть соображения производительности.Я думаю, что было бы интересно обсудить эту тему, учитывая, что новые планы ECMAScript Harmony отказались от планов 4.0 в отношении пространства имен и упаковки.
Я стараюсь следовать соглашению Yahoo о создании одного родительского объекта в глобальной области видимости, который содержал бы все;
var FP = {};
FP.module = {};
FP.module.property = 'foo';
Чтобы убедиться, что вы не перезаписываете существующий объект, вы должны сделать что-то вроде:
if(!window.NameSpace) {
NameSpace = {};
}
или
var NameSpace = window.NameSpace || {};
Таким образом, вы можете поместить это в начало каждого файла вашего приложения / веб-сайта, не беспокоясь о перезаписи объекта пространства имен.Кроме того, это позволило бы вам писать модульные тесты для каждого файла по отдельности.
Тот Самый Библиотека ЮИ в библиотеке есть код, который обрабатывает пространство имен с помощью функции, которая может показаться вам предпочтительной.Другие библиотеки также могут делать это.
В качестве альтернативы точке или подчеркиванию вы могли бы использовать символ знака доллара:
var namespaces$com$example = "data";
Мне тоже нравится это (Источник):
(function() {
var a = 'Invisible outside of anonymous function';
function invisibleOutside() {
}
function visibleOutside() {
}
window.visibleOutside = visibleOutside;
var html = '--INSIDE Anonymous--';
html += '<br/> typeof invisibleOutside: ' + typeof invisibleOutside;
html += '<br/> typeof visibleOutside: ' + typeof visibleOutside;
contentDiv.innerHTML = html + '<br/><br/>';
})();
var html = '--OUTSIDE Anonymous--';
html += '<br/> typeof invisibleOutside: ' + typeof invisibleOutside;
html += '<br/> typeof visibleOutside: ' + typeof visibleOutside;
contentDiv.innerHTML += html + '<br/>';
Используйте объектный литерал и либо this
объект или явное имя для создания пространства имен на основе родственных свойств локальной переменной, которая содержит функцию.Например:
var foo = { bar: function(){return this.name; }, name: "rodimus" }
var baz = { bar: function(){return this.name; }, name: "optimus" }
console.log(foo.bar());
console.log(baz.bar());
Или без явного name
собственность:
var foo = { bar: function rodimus(){return this; } }
var baz = { bar: function optimus(){return this; } }
console.log(foo.bar.name);
console.log(baz.bar.name);
Или без использования this
:
var foo = { bar: function rodimus(){return rodimus; } }
var baz = { bar: function optimus(){return optimus; } }
console.log(foo.bar.name);
console.log(baz.bar.name);
Используйте RegExp
или Object
функции конструктора для добавления свойств имени к переменным счетчика и другим распространенным именам, затем используйте hasOwnProperty
тест для проверки:
var foo = RegExp(/bar/);
/* Add property */
foo.name = "alpha";
document.body.innerHTML = String("<pre>" + ["name", "value", "namespace"] + "</pre>").replace(/,/g, "	");
/* Check type */
if (foo.hasOwnProperty("name"))
{
document.body.innerHTML += String("<pre>" + ["foo", String(foo.exec(foo)), foo.name] + "</pre>").replace(/,/g, "	");
}
/* Fallback to atomic value */
else
{
foo = "baz";
}
var counter = Object(1);
/* Add property */
counter.name = "beta";
if (counter.hasOwnProperty("name"))
{
document.body.innerHTML += String("<pre>" + ["counter", Number(counter), counter.name] + "</pre>").replace(/,/g, "	");
}
else
{
/* Fallback to atomic value */
counter = 0;
}
DOM использует следующее соглашение для определения пространства имен HTML и SVG элементов интерфейса:
- HTMLTitleElement Элемент
- SVGTitleElement Элемент
- SVGScriptЭлемент
- HTMLScriptЭлемент
Ядро JavaScript использует прототипы для создания пространства имен toString
метод как простая форма полиморфизма.
Ссылки
- Работает ли javascript автоматически?
- Получение родственного значения ключа в литерале объекта JavaScript
- MDN:Операторы JavaScript - это как объектный метод
- Lua:техническое примечание 7 - Модули и пакеты
- HTMLTitleElement.webidl
- SVGTitleElement.webidl
- SVGScriptElement.webidl
- HTMLScriptЭлемент.webidl
- Имена функций в ES6
- Спецификация языка ECMAScript 2015 - 19.2.4.2 Экземпляры функций:название | ECMA-262 6-е издание