Пространство имен JavaScript
Я хочу создать глобальное пространство имен для моего приложения и в этом пространстве имен мне нужны другие пространства имен:
например.
Dashboard.Ajax.Post()
Dashboard.RetrieveContent.RefreshSalespersonPerformanceContent();
Я также хочу поместить их в отдельные файлы:
- ajax.js
- RetrieveContent.js
Однако я попытался использовать этот метод, однако это не сработает, потому что одно и то же имя переменной используется для пространства имен в 2 отдельных мест. Может ли кто-нибудь предложить альтернативу?
Спасибо.
Ответы
Ответ 1
Вам просто нужно убедиться, что вы не топаете на свой объект пространства имен, если он уже создан. Что-то вроде этого будет работать:
(function() {
// private vars can go in here
Dashboard = Dashboard || {};
Dashboard.Ajax = {
Post: function() {
...
}
};
})();
И файл RetrieveContent
будет определен аналогично.
Ответ 2
Здесь - очень хорошая статья о различных "шаблонах модулей" в JavaScript. Существует очень приятный небольшой раздел о том, как вы можете добавлять модули или пространства имен и поддерживать личное состояние кросс файла. То есть код в отдельных файлах будет выполняться последовательно и правильно дополнять пространство имен после его выполнения.
Я не изучил эту технику полностью, поэтому нет promises... но вот основная идея.
dashboard.js
(function(window){
var dashboard = (function () {
var my = {},
privateVariable = 1;
function privateMethod() {
// ...
}
my.moduleProperty = 1;
my.moduleMethod = function () {
// ...
};
return my;
}());
window.Dashboard = dashboard;
})(window);
dashboard.ajax.js
var dashboard = (function (my) {
var _private = my._private = my._private || {},
_seal = my._seal = my._seal || function () {
delete my._private;
delete my._seal;
delete my._unseal;
},
_unseal = my._unseal = my._unseal || function () {
my._private = _private;
my._seal = _seal;
my._unseal = _unseal;
};
// permanent access to _private, _seal, and _unseal
my.ajax = function(){
// ...
}
return my;
}(dashboard || {}));
dashboard.retrieveContent.js
var dashboard = (function (my) {
var _private = my._private = my._private || {},
_seal = my._seal = my._seal || function () {
delete my._private;
delete my._seal;
delete my._unseal;
},
_unseal = my._unseal = my._unseal || function () {
my._private = _private;
my._seal = _seal;
my._unseal = _unseal;
};
// permanent access to _private, _seal, and _unseal
my.retrieveContent = function(){
// ...
}
return my;
}(dashboard || {}));
Ответ 3
Функция Yahoo Namespace предназначена именно для этой проблемы.
Добавлено:
Доступен источник этой функции. Вы можете скопировать его в свой собственный код, если хотите, изменить корень из YAHOO на что-то еще и т.д.
Ответ 4
Существует несколько библиотек, которые уже предлагают такую функциональность, если вы хотите использовать или исследовать предварительно искушенное (то есть тестируемое) решение.
Самый простой и самый простой, с которым нужно работать, вероятно, jQuery.extend
, с аргументом deep
установлено значение true. (Причина, по которой я говорю, что это ошибка, - это не потому, что я думаю, что jQuery.extend
страдает от меньших ошибок, чем любая другая библиотека, но потому, что он предлагает четкую возможность глубокого копирования атрибутов от отправителя к получателю - который большинство других библиотек явно не предоставляют. Это предотвратит появление многих затруднительных диагностических ошибок в вашей программе, потому что вы использовали мелкую копию extend
и теперь выполняете функции в контекстах, которые вы не ожидали от них для выполнения. (Если, однако, вы осознаете, как будете расширять свою базовую библиотеку при разработке своих методов, это не должно быть проблемой.)
Ответ 5
Создав объект NS, вы должны просто добавить его туда, где когда-либо. Хотя вы можете попробовать var NS = NS || {};
, чтобы гарантировать, что объект NS существует и не перезаписывается.
// NS is a global variable for a namespace for the app code
var NS = NS || {};
NS.Obj = (function() {
// Private vars and methods always available to returned object via closure
var foo; // ...
// Methods in here are public
return {
method: function() {
}
};
}());
Ответ 6
Вы можете сделать что-то вроде этого...
HTML-страница с использованием библиотеки с именами:
<html>
<head>
<title>javascript namespacing</title>
<script src="dashboard.js" type="text/javascript"></script>
<script src="ajax.js" type="text/javascript"></script>
<script src="retrieve_content.js" type="text/javascript"></script>
<script type="text/javascript">
alert(Dashboard.Ajax.Post());
alert(Dashboard.RetrieveContent.RefreshSalespersonPerformanceContent());
Dashboard.RetrieveContent.Settings.Timeout = 1500;
alert(Dashboard.RetrieveContent.Settings.Timeout);
</script>
</head>
<body>
whatever...
</body>
</html>
Dashboard.js:
(function(window, undefined){
var dashboard = {};
window.Dashboard = dashboard;
})(window);
ajax.js:
(function(){
var ajax = {};
ajax.Post = function() { return "Posted!" };
window.Dashboard.Ajax = ajax
})();
Retrieve_Content.js:
(function(){
var retrieveContent = {};
retrieveContent.RefreshSalespersonPerformanceContent = function() {
return "content retrieved"
};
var _contentType;
var _timeout;
retrieveContent.Settings = {
"ContentType": function(contentType) { _contentType = contentType; },
"ContentType": function() { return _contentType; },
"Timeout": function(timeout) { _timeout = timeout; },
"Timeout": function() { return _timeout; }
};
window.Dashboard.RetrieveContent = retrieveContent;
})();
Dashboard.js выступает в качестве отправной точки для всех имён пространства имен. Остальные определяются в соответствующих файлах. В Retrieve_Content.js я добавил дополнительные свойства там под Settings
, чтобы дать представление о том, как это сделать, если это необходимо.
Ответ 7
Я считаю, что шаблон модуля может быть прямо вверх по вашей аллее. Здесь хорошая статья о различных модульных шаблонах.
http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth
Ответ 8
Я настоятельно рекомендую вам использовать эту технику:
https://github.com/mckoss/namespace
namespace.lookup('com.mydomain.mymodule').define(function (ns) {
var external = namespace.lookup('com.domain.external-module');
function myFunction() {
...
}
...
ns.extend({
'myFunction': myFunction,
...
});
});
Я использую этот шаблон в течение нескольких лет; Я хочу, чтобы больше библиотек делало то же самое; это облегчило мне обмен кода между моими другими проектами.
Ответ 9
Я написал эту функцию, чтобы упростить создание пространств имен. Маби, это поможет тебе.
function ns(nsstr) {
var t = nsstr.split('.');
var obj = window[t[0]] = window[t[0]] || {};
for (var i = 1; i < t.length; i++) {
obj[t[i]] = obj[t[i]] || {};
obj = obj[t[i]];
}
}
ns('mynamespace.isawesome.andgreat.andstuff');
mynamespace.isawesome.andgreat.andstuff = 3;
console.log(mynamespace.isawesome.andgreat.andstuff);
Ответ 10
bob.js может помочь в определении ваших пространств имен (среди прочих):
bob.ns.setNs('Dashboard.Ajax', {
Post: function () { /*...*/ }
});
bob.ns.setNs('Dashboard.RetrieveContent', {
RefreshSalespersonPerformanceContent: function () { /*...*/ }
});
Ответ 11
Реализация:
namespace = function(packageName)
{
// Local variables.
var layers, layer, currentLayer, i;
// Split the given string into an array.
// Each element represents a namespace layer.
layers = packageName.split('.');
// If the top layer does not exist in the global namespace.
if (eval("typeof " + layers[0]) === 'undefined')
{
// Define the top layer in the global namesapce.
eval(layers[0] + " = {};");
}
// Assign the top layer to 'currentLayer'.
eval("currentLayer = " + layers[0] + ";");
for (i = 1; i < layers.length; ++i)
{
// A layer name.
layer = layers[i];
// If the layer does not exist under the current layer.
if (!(layer in currentLayer))
{
// Add the layer under the current layer.
currentLayer[layer] = {};
}
// Down to the next layer.
currentLayer = currentLayer[layer];
}
// Return the hash object that represents the last layer.
return currentLayer;
};
Результат:
namespace('Dashboard.Ajax').Post = function() {
......
};
namespace('Dashboard.RetrieveContent').RefreshSalespersonPerformanceContent = function() {
......
};
Gist:
namespace.js