Есть ли «краткий» способ сделать пространство имен в JavaScript?

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

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

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

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

16.08.2008 05:57:37
8 ОТВЕТОВ
РЕШЕНИЕ

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

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

19
22.07.2012 06:54:14
Хотя сейчас com_exampleэто будет частью глобального объекта. Предположим, что мы добавили еще много объектов com_something_else, com_etcтогда мы все еще загрязняем корневой уровень глобального объекта. Разве это не было бы предпочтительным, если бы у нас был только один comобъект в глобальном, куда были добавлены все другие объекты? Кроме того, мы не хотим перезаписывать какие-либо существующие объекты, что, если используются несколько библиотек.
Peter 4.10.2011 05:00:28
@Peter: если несколько библиотек определяют одни и те же символы, у вас будут проблемы, несмотря ни на что; Вот почему библиотеки, такие как jQuery, идут на все, чтобы объединить все в один глобальный объект. Я не хотел, чтобы вы использовали несколько объектов верхнего уровня, просто имитация пространств имен с глубоко вложенными объектами на самом деле ничего не купит за сумасшедшие длинные имена объектов. Смотрите мой последний пример для более практичного метода: используйте единственное глобальное имя, которое вряд ли столкнется, а затем метод, который позволяет разрозненным частям кода добавлять объекты к нему.
Shog9 4.10.2011 15:39:14

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

3
16.08.2008 16:06:03

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

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

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

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

12
17.08.2008 05:31:35

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

var FP = {};
FP.module = {};
FP.module.property = 'foo';
6
17.08.2008 10:46:13

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

var namespaces$com$example = "data"; 
1
18.08.2008 01:38:36
Какую пользу это дает?
eyelidlessness 25.10.2008 04:11:08
Делая это таким образом, вам не нужно определять свои пространства имен как объект с вложенными внутренними объектами. Вы можете просто определить имя в любом месте.
Mark Cidade 28.10.2008 04:04:54
Я до сих пор не вижу преимущества использования знака $ вместо точки или подчеркивания. Я думаю, что знак $ делает слово более трудным для чтения, чем точка или подчеркивание.
rodrigo-silveira 17.02.2012 21:06:55
Я думаю, что это намного хуже, чем использование вложенных объектов - у вас есть тонны отдельных переменных, которые - независимо от того, глобальные или локальные - сделают отладку адом, когда вы посмотрите на определенные в настоящее время переменные.
ThiefMaster 10.03.2012 11:02:36

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

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

или

var NameSpace = window.NameSpace || {};

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

5
18.08.2008 14:55:22

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

(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.06.2009 21:16:12

Используйте литерал объекта и либо 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);

Используйте функции конструктора RegExpor Objectдля добавления свойств имени к переменным счетчика и другим распространенным именам, а затем используйте hasOwnPropertyтест для проверки:

 var foo = RegExp(/bar/);
 
/* Add property */
foo.name = "alpha";

document.body.innerHTML = String("<pre>" + ["name", "value", "namespace"] + "</pre>").replace(/,/g, "&#09;");

/* Check type */
if (foo.hasOwnProperty("name")) 
  {
  document.body.innerHTML += String("<pre>" + ["foo", String(foo.exec(foo)), foo.name] + "</pre>").replace(/,/g, "&#09;");
  }

/* 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, "&#09;");
  } 
else 
  {
  /* Fallback to atomic value */
  counter = 0;
  }

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

  • HTMLTitleElement
  • SVGTitleElement
  • SVGScriptElement
  • HTMLScriptElement

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

Ссылки

0
23.05.2017 12:26:23