Предпочтительный метод для пространства имен javascript

Мой код превратится в беспорядок, если я не начну использовать какую-то технику пространства имен. Я относительно новичок в программировании больших проектов javascript, но имею значительный опыт системного программирования на C++/java/python и т. д.

В основном я пытаюсь определить, какой метод является предпочтительным для создания пространств имен javascript, и каковы плюсы/минусы для каждого метода.

Например, я мог бы использовать любой из следующих трех методов:

var proj.lib.layout = {
  "centreElem":     
  function (elem, W, H){

  },

  "getAbsolutePosition":
  function (elem){

  }
};

OR

var proj.lib.layout = {};
(function(){
  var l = proj.lib.layout;

  l.centreElem = function (elem, winW, winH){
    ..
  }

  l.getAbsolutePosition = function (elem){
    ..
  }
})();

OR

var proj.lib.layout = new function(){
  function centreElem(elem, W, H){
    ..
  }

  function getAbsolutePosition(elem){
    ..
  }

  this.centreElem          = centreElem;
  this.getAbsolutePosition = getAbsolutePosition;
} ();

Есть и другие способы сделать это слишком очевидно, но это были первые, которые я увидел и о которых подумал. Может ли кто-нибудь сказать, что есть «лучший» метод, или, по крайней мере, указать мне на некоторые плюсы и минусы, из которых я могу оценить, какой из них лучше для меня?


person rewolf    schedule 01.07.2011    source источник
comment
возможный дубликат объявления пространства имен JavaScript   -  person jball    schedule 01.07.2011


Ответы (4)


Обратите внимание, что вам нужно создать все промежуточные объекты, прежде чем вы сможете назначить такой подобъект:

window.one.two.three = {}; // fails
window.one = { two: { three: {} } };

Рассмотрите возможность написания метода пространства имен, чтобы вы могли унифицировать код пространства имен. Например:

window.proj = {};
// n - {String} - A string representing a namespace to create on proj
// returns an object you can assign values to
window.proj.namespace = function(n) { /* ... */ };

(function(NS) {
    NS.myMethod = function() {};
    NS.myOtherMethod = function() {};
    NS.myProperty = "FOO";
})(proj.namespace('lib.layout'));

assert(proj.lib.layout.myProperty === "FOO");
person Nick Husher    schedule 01.07.2011
comment
Сначала я был сбит с толку тем, что вы имели в виду под функцией namespace(), но теперь я предназначен для выполнения общего создания пространств имен, таких как настройка промежуточных пространств имен. Хорошая идея и спасибо. Я предполагаю, что вы одобряете и рекомендуете эту форму объявления пространства имен (самостоятельная анонимная функция). - person rewolf; 01.07.2011
comment
Кроме того, это обычно называется шаблоном модуля во вселенной Javascript. - person Nick Husher; 04.07.2011
comment
Кроме того, я рассматривал возможность включения реализации функции пространства имен, но это довольно распространенная функция фреймворка. Основной алгоритм — разбить на ., перебрать куски, создать необходимые промежуточные объекты. Наконец, верните ссылку на последний созданный объект. - person Nick Husher; 04.07.2011

Мой предпочтительный метод состоит в том, чтобы иметь один объект (чье имя обычно короткое, 2-3 символа и все в верхнем регистре) в качестве моего пространства имен, в котором будут содержаться все другие объекты.

Показанный ниже метод (который наиболее точно соответствует вашему второму примеру) также показывает, как скрыть любые частные функции:

// In this example the namespace is "QP"
if (!QP) {
    var QP = {};
};

// Define all objects inside an closure to allow "private" functions
(function() {

     QP.examplePublicFunction = function() {
         ...
     }

     function examplePrivateFunction() {
         ...
     }

})();

Этот метод используется рядом других библиотек JavaScript, например json2.js.

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

person Justin    schedule 01.07.2011

В библиотеке Javascript Google Closure используется этот стиль (который не совсем похож на другие из ваших примеров)

goog.math.clamp = function(value, min, max) {
  return Math.min(Math.max(value, min), max);
};

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

person Peter Lyons    schedule 01.07.2011
comment
Да, я делал это, чтобы не вводить полную цепочку для каждой функции. И помещение его в самовыполняющуюся функцию означало, что временная l не будет существовать глобально. Я полагаю, что это также немного быстрее, поскольку вам не нужно пересекать цепочку во время назначения, а тела функций, которые ссылаются на переменные/функции в одном и том же пространстве имен, также не должны указывать цепочку. - person rewolf; 01.07.2011

По сути, все три примера используют одну и ту же технику «пространства имен», то есть создают базовый объект (ваше пространство имен), а затем дополняют его своими функциями.

обычно корневое пространство имен пишется заглавными буквами:

if (typeof (MYAPP) == "undefined" || !MYAPP) {
    var MYAPP= {}
};

Затем вы можете добавлять функциональные возможности к этому базовому объекту различными способами. В вашем коде вы показываете три из них, но каждый из них дает один и тот же результат, вы можете вызвать две эти функции:

proj.lib.layout.centreElem(elem, W, H);
proj.lib.layout. getAbsolutePosition(elem);
person Nicola Peluchetti    schedule 01.07.2011