Есть ли опасности, связанные с использованием пространств имен JavaScript? - PullRequest
4 голосов
/ 19 января 2012

Существуют ли какие-либо опасности / предостережения, которые следует учитывать при создании пространств имен JavaScript?

Наш проект довольно обширный, и мы запускаем много файлов JavaScript (более 20, ожидая большего). Невозможно обеспечить поддержку кода без использования пространств имен, поэтому мы реализуем их так:

var namespace1 = {

  doSomething: function() {
    ...
  },

  doSomethingElse: function() {
    ...
  }

}

А затем, чтобы создать иерархии, мы связываем их так:

var globalNamespace = {
  functions1: namespace1,
  functions2: namespace2,
  ...

}

Это отлично работает, но по сути это "хитрость", заставляющая JS вести себя так, как будто у него есть пространства имен. Хотя этот метод часто используется, кажется, что большая часть литературы посвящена тому, как это сделать, а не тому, есть ли какие-либо возможные недостатки. Поскольку мы пишем больше кода JS, это быстро становится неотъемлемой частью работы нашей системы. Поэтому важно, чтобы он работал без проблем.

Были ли ситуации, в которых эта "индуцированная" система пространств имен вызывала у вас ошибки или иным образом требовала особого внимания? Можем ли мы ожидать одинакового поведения во всех браузерах?

Ответы [ 4 ]

3 голосов
/ 19 января 2012

То, как вы определяете пространства имен в вашем примере, похоже, создает глобалы из каждого пространства имен, так что в итоге вы получаете

window.namespace1
window.namespace2
window.globalNamespace
window.globalNamespace.namespace1
window.globalNamespace.namespace2

Так что, если у вас есть что-то, что сгущает window.namespace1, оно также будет сжиматься window.globalNamespace.namespace1

edit:

Вот как мы справились с этой проблемой:

namespacing = {
    init: function(namespace) {
        var spaces = []; 
        namespace.split('.').each(function(space) {
            var curSpace = window,
                i;  

            spaces.push(space);
            for (i = 0; i < spaces.length; i++) {
                if (typeof curSpace[spaces[i]] === 'undefined') {
                    curSpace[spaces[i]] = {}; 
                }   
                curSpace = curSpace[spaces[i]];
            }   
        });
    }
};

Затем вы используете это так:

namespacing.init('globalNamespace.namespace1');

globalNamespace.namespace1.doSomething = function() { ... };

Таким образомвам не нужно вводить новые глобальные переменные, и вы можете уверенно добавлять в существующее пространство имен, не забивая в нем другие объекты.

2 голосов
/ 19 января 2012

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

Но если вам нужна модульность, почему бы не использовать (относительно) простой фреймворк, такой как require.js ? Это позволит вам и вашей команде писать код в модульном режиме и позволит команде «импортировать» эти модули в случае необходимости:

require(["helper/util"], function() {
  //This function is called when scripts/helper/util.js is loaded.
});

Require.js позаботится о зависимостях, а также предотвратит загрязнение глобального пространства имен.

1 голос
/ 19 января 2012

Вот как я бы порекомендовал это сделать, чтобы вы полностью не входили в глобальную область, за исключением вашего "базового" пространства имен.Мы делаем что-то подобное, где я работаю.Допустим, вы работаете на Acme co и хотите, чтобы ACME было вашим базовым пространством имен.

В верхней части каждого файла вы должны добавить:

if (!window.ACME) { window.ACME = {} }

Затем просто перейдите и определитевсе, что вы хотите с точки зрения этого.

ACME.Foo = {
  bar: function () { console.log("baz"); }
}

Если вы хотите более глубокий уровень пространства имен, вы просто делаете то же самое для каждого уровня.

if (!window.ACME) { window.ACME = {} }
if (!ACME.Foo) { ACME.Foo = {} }

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

1 голос
/ 19 января 2012

Мы используем аналогичную систему на работе, и она отлично справляется со своей задачей. Я не вижу никаких недостатков; это просто объекты и свойства. По этой же причине кросс-браузерная совместимость должна быть хорошей. Вы можете в конечном итоге написать несколько длинных имен для разрешения конкретной функции, например Foo.Bar.Test.Namespace2.Function, но даже тогда это можно решить, присвоив ее переменной перед рукой.

...