Пространство имен JavaScript - PullRequest
       5

Пространство имен JavaScript

15 голосов
/ 05 августа 2010

Я хочу создать глобальное пространство имен для своего приложения, и в этом пространстве имен я хочу другие пространства имен:

Например,

Dashboard.Ajax.Post()

Dashboard.RetrieveContent.RefreshSalespersonPerformanceContent();

Я также хочу разместить их в отдельных файлах:

  • Ajax.js
  • RetrieveContent.js

Однако я пытался использовать этот метод, однако он не будет работать, потому чтоодно и то же имя переменной используется для пространства имен в 2 отдельных местах.Кто-нибудь может предложить альтернативу?

Спасибо.

Ответы [ 11 ]

9 голосов
/ 05 августа 2010

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

(function() {
    // private vars can go in here


    Dashboard = Dashboard || {};
    Dashboard.Ajax = {
        Post: function() {
            ...
        }
    };
})();

И файл RetrieveContent будет определен аналогично.

7 голосов
/ 17 июня 2011

Здесь - очень хорошая статья о различных «шаблонах модулей» в JavaScript. Есть очень хороший маленький раздел о том, как вы можете расширять модули или пространства имен и поддерживать частное состояние между файлами. То есть код в отдельных файлах будет выполняться последовательно и правильно расширять пространство имен после его выполнения.

Я не изучил эту технику полностью, поэтому никаких обещаний ... но вот основная идея.

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 || {}));
4 голосов
/ 05 августа 2010

Функция Yahoo Namespace предназначена именно для этой проблемы.

Добавлено:

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

3 голосов
/ 05 августа 2010

Создав объект NS, вы просто сможете добавить к нему откуда угодно. Хотя вы можете попробовать var NS = NS || {};, чтобы убедиться, что объект NS существует и не перезаписан.

// NS is a global variable for a namespace for the app's 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() {

    }
  };

}());
3 голосов
/ 05 августа 2010

Есть несколько библиотек, которые уже предлагают такую ​​функциональность, если вы хотите использовать или исследовать предварительно запеченное (то есть проверенное) решение.

Самым простым и наиболее безошибочным для использования является, вероятно, jQuery.extend с аргументом deep, установленным в true.(Причина, по которой я говорю, что она не содержит ошибок, заключается не в том, что я думаю, что jQuery.extend страдает от меньшего количества ошибок, чем в любой другой библиотеке, - а потому, что она предлагает четкую возможность глубокого копирования атрибутов от отправителя к получателю, чтобольшинство других библиотек явно не предоставляют. Это предотвратит появление в вашей программе многих трудно диагностируемых ошибок, поскольку вы использовали мелкую копию extend и теперь имеете функции, выполняемые в контекстахвы не ожидали, что они будут выполняться. (Однако, если вы знаете, как будете расширять свою базовую библиотеку при разработке ваших методов, это не должно быть проблемой.)

1 голос
/ 21 августа 2014

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

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);
1 голос
/ 19 марта 2011

Я настоятельно рекомендую вам использовать эту технику:

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,
     ...
  });
});

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

1 голос
/ 05 августа 2010

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

http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth

1 голос
/ 05 августа 2010

Вы могли бы сделать что-то вроде этого ...

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, чтобы дать представление о том, как это сделать, если необходимо.

0 голосов
/ 07 апреля 2015

Реализация:

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

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