Пространство имен библиотеки JavaScript, как необязательный - PullRequest
4 голосов
/ 24 января 2011

Я собираюсь приступить к созданию библиотеки JS, которая будет иметь несколько модулей.Предположим, библиотека называется Library, а два модуля будут называться One и Two.Я бы хотел, чтобы конечные пользователи могли вызывать библиотеку двумя различными способами:

Library.One.somefunction(params)

или

somefunction(params)

По сути, я хочу дать конечным пользователям возможностьв том числе пространство имен или нет.Есть ли хороший способ сделать это?Кроме того, есть ли хороший способ сделать это, если я также хочу предоставить уменьшенную версию библиотеки?Эта библиотека - кое-что, что я мог закончить в Node.js;сейчас я собираюсь использовать его сам, но я хочу разработать его таким образом, чтобы в будущем не было слишком сложно обратиться к совместному проекту.

Любые ссылки, которые вы можете указать мнебыло бы здорово, спасибо!

Ответы [ 6 ]

5 голосов
/ 24 января 2011

Если вы используете Node.js , вы можете использовать модульную систему CommonJS .

math.js (ваша библиотека)

exports.add = function() {
    for (var i = arguments.length; i--;) {
        sum += arguments[i];
    }
    return sum;
};

program.js (кто-то использует это ...)

var MyMath = require('math');
console.log(MyMath.add(1, 2)); // 3

// ... in different ways

var add = require('math').add;
console.log(add(1, 2)); // 3
2 голосов
/ 24 января 2011

Основная идея сделать необязательное «пространство имен» состоит в том, чтобы назначить функции глобальной области действия, которой является window объект:

window.somefunction = Library.One.somefunction;

Вы можете написать include функцию, которая работает аналогично другим языкам:

var include = function (library, p) {
    if (!p) {
        for (var prop in library) {
            if (library.hasOwnProperty(prop)) {
                window[prop] = library[prop];
            }
        }
    } else {
        window[p] = library[p];
    }
};

Тогда просто сделайте, как требуется:

include(Library.One);

Или использовать только определенные функции:

include(Library.One, 'somefunction');

Предупреждения

  1. При выполнении функций без точечной нотации (One.somefunction) ключевое слово this будет ссылаться на window, а не Library.One. Это не проблема, если вы вообще не используете this. Если у вас есть данные для обмена между функциями, вы можете сделать это, используя область закрытия вместо this:

    var Library = {};
    
    (function () {
        // I'm a closure, I have local scope
        var sharedData = "I'm shared but private to this scope";
    
        Library.One = {};
    
        Library.One.funcOne = function () {
            alert(sharedData);
        };
    
        Library.One.funcTwo = function () {
            sharedData += "!";
        };
    
    }) ();
    
  2. Другие советуют не делать ваши методы глобальными. Это связано с тем, что, будучи глобальным, он становится глобальным для всех файлов и поэтому может конфликтовать с другим кодом. Что вы можете сделать, так это изменить указанную выше функцию import, чтобы создать новый объект, и назначить все этому объекту перед его возвратом. Тогда файлы, которые нуждаются в ярлыках для определенных библиотек, могут делать:

    (function () {
        var _ = include(Library.One); // This stays within this scope
        _.somefunction();
    })();
    
1 голос
/ 24 января 2011

ну, я не знаю, что вы подразумеваете под "хорошим путем".
Прежде всего, вся цель пространства имен - собирать связанные переменные, а не разбрасывать их по общему пространству имен. Лично я бы не использовал такую ​​вещь, но вы могли бы перебирать объекты вашего пространства имен и прикреплять их к окну:

for(var i in Namespace)
    if(Namespace.hasOwnProperty(i))
        window[i] = Namespace[i];
0 голосов
/ 24 января 2011

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

Для первой части просто объявите глобально ваше пространство имен библиотеки:

var Library = {};

и затем начните заполнять его модулями:

Library.One = {};
Library.Two = {};

и затем начните добавлять функциональность к этим модулям.

(function($) {
  var $.froobString = function(s) { .... };
  ...etc...
})(Library.One);

(Здесь я сделал это как самовыполняющуюся анонимную функцию, которая передает Library.One как $.)

Чтобы преобразовать все это в глобальные переменные, создайте следующую процедуру:

var convertToGlobals = function(module) {
  for (name in module) {
    window[name] = module[name];
  }
};
convertToGlobals(Library.One)

Но опять же я бы советовал против этого.

0 голосов
/ 24 января 2011

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

1) Я хочу использовать пространства имен
2) Я хочу иметь возможность доступа к функциональности пространства имен без пространства имен.

в основном 2 - это "Я не хочу пространств имен".

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

0 голосов
/ 24 января 2011

Вы могли бы сделать это довольно легко, но вы уверены, что хотите сделать все методы глобальными свойствами?

Вы могли бы реализовать это так (очень упрощенно):

(function( window, undefined ) {

    // Your code setting up namespaces
    var Library = {One:{},Two:{}};

       // function for adding library code to both namespaces.
       // Could be modified to accept an Array of functions/names
    function addToLibraryOne( id, fn ) {
        window[id] = Library.One[id] = fn;
    }

       // add a function
    addToLibraryOne( "somefunction", function( params ) {
           // function code
    });

    window.Library = Library;

})( window );

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

По крайней мере, я бы сделал свойства global опцией, а затем добавил бы функцию, добавляющую только те свойства, если эта опциявыбран.

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