Есть ли "краткий" способ сделать пространство имен в JavaScript? - PullRequest
13 голосов
/ 16 августа 2008

Я часто сталкивался с сайтами, которые помещают весь свой JavaScript в структуру namespace, например:

namespaces = { com : { example: { example.com's data} }

Однако для безопасной настройки по отношению к другим структурам пространства имен, по-видимому, требуется относительно большой объем кода (определенный как> 2 строки). Мне было интересно, знает ли кто-нибудь о кратком способе сделать это? Кроме того, существует ли относительно стандартный / последовательный способ его структурирования? Например, является ли пространство имен com непосредственно присоединенным к глобальному объекту, или оно присоединено через объект пространства имен?

[Edit: к сожалению, очевидно, {com = { ... } } не достигнет ничего, что я хотел, спасибо Shog9 за то, что указал на это.]

Ответы [ 8 ]

19 голосов
/ 16 августа 2008

Javascript не имеет автономных пространств имен. Он имеет функции, которые могут предоставлять область для разрешения имен, и объекты, которые могут вносить вклад в именованные данные, доступные в данной области.

Вот ваш пример, исправленный:

var namespaces = { com: { example: { /* example.com's data */ } } }

Это переменная namespaces, которой присваивается литерал объекта. Объект содержит одно свойство: com, объект с одним свойством: example, объект, который предположительно будет содержать что-то интересное.

Итак, вы можете ввести что-то вроде namespaces.com.example. somePropertyOrFunctionOnExample и все будет работать. Конечно, это тоже смешно. У вас нет иерархического пространства имен, у вас есть объект, содержащий объект, содержащий объект с вещами, которые вам действительно нужны.

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() { /* ... */ }
       };
    })();

... что, ИМХО, достаточно кратко.

12 голосов
/ 17 августа 2008

Вот интересная статья Питера Мишо о Пространстве имен Javascript . Он обсуждает 3 различных типа пространства имен Javascript:

  1. Префикс пространства имен
  2. Пространство имен одного объекта
  3. Пространство имен вложенных объектов

Я не буду заниматься плагиатом того, что он сказал здесь, но я думаю, что его статья очень информативна.

Питер даже зашел так далеко, что указал, что с некоторыми из них существуют соображения производительности. Я думаю, что эту тему было бы интересно обсудить, учитывая, что в новых планах ECMAScript Harmony отказались от планов 4.0 в отношении пространства имен и упаковки.

6 голосов
/ 17 августа 2008

Я пытаюсь следовать соглашению Yahoo о выделении единственного родительского объекта в глобальную область видимости, содержащего все;

var FP = {};
FP.module = {};
FP.module.property = 'foo';
5 голосов
/ 18 августа 2008

Чтобы убедиться, что вы не перезаписываете существующий объект, вы должны сделать что-то вроде:

if(!window.NameSpace) {
    NameSpace = {};
}

или

var NameSpace = window.NameSpace || {};

Таким образом, вы можете поместить это в начало каждого файла в вашем приложении / веб-сайте, не беспокоясь о перезаписи объекта пространства имен. Кроме того, это позволит вам написать модульные тесты для каждого файла в отдельности.

3 голосов
/ 16 августа 2008

Библиотека YUI содержит код, который обрабатывает пространство имен с помощью функции, которая может оказаться предпочтительной. Другие библиотеки также могут делать это.

1 голос
/ 19 июня 2009

Мне также нравится это ( источник ):

(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/>';​
1 голос
/ 18 августа 2008

В качестве альтернативы точке или подчеркиванию вы можете использовать знак доллара:

var namespaces$com$example = "data"; 
0 голосов
/ 24 марта 2012

Используйте литерал объекта и либо объект 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("" + ["name", "value", "namespace"] + "
"). Заменить (/, / г," "); / * Тип проверки * / if (foo.hasOwnProperty ("name")) { document.body.innerHTML + = String ("
" + ["foo", String(foo.exec(foo)), foo.name] + "
"). replace (/, / g, ""); } / * Откат к атомной стоимости * / еще { foo = "баз"; } var counter = Object (1); / * Добавить недвижимость * / counter.name = "beta"; if (counter.hasOwnProperty ("name")) { document.body.innerHTML + = String ("
" + ["counter", Number(counter), counter.name] + "
"). replace (/, / g, ""); } еще { / * Откат к атомной стоимости * / счетчик = 0; }

DOM использует следующее соглашение для определения пространства имен HTML и определения интерфейса SVG Element:

  • HTMLTitleElement
  • SVGTitleElement
  • SVGScriptElement
  • HTMLScriptElement

Ядро JavaScript использует прототипы для пространства имен метода toString как простой формы полиморфизма.

Ссылки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...