Dark_Knight
@Dark_Knight
Game Dev

Как использовать шаблон namespace?

Здравствуйте, подскажите пожалуйста.
Нашел у Эдди паттерн модуль и не знаю, как правильно его использовать,то есть есть код:
var myApp = myApp || {};

function extend(ns, ns_string) {
    var parts = ns_string.split('.'),
        parent = ns,
        pl, i;

    if (parts[0] == "myApp") {
        parts = parts.slice(1);
    }
    pl = parts.length;

    for (i = 0; i < pl; i++) {
        //create a property if it doesnt exist
        if (typeof parent[parts[i]] == 'undefined') {
            parent[parts[i]] = {};
        }
        parent = parent[parts[i]];
    }
    return parent;
}
extend(myApp, 'myApp.modules.module2');

И есть моя функция, которая, как я понял уже добавлена в пространство имен
function module2() {
    this.a = 'test';
}

но консоль не выводи данные это функции
console.log(myApp);
Вопсрос: как правильно использовать этот шаблон? То есть если я добавил в пространство имен модуль, то где писать тело этого модуля?
  • Вопрос задан
  • 2312 просмотров
Решения вопроса 1
mlnkv
@mlnkv
JavaScript Developer
var App = {
  parent: {
    parent2: { // это ваш модуль, здесь его и описываем
      method: function() {
        return "Hello!";
      }
    }
  }
}

var method = extend(App, "parent.parent2.method"); // "Hello!"

console.log(method); // "Hello!"
console.log(App.parent.parent2.method()); // "Hello!"
console.log(method == App.parent.parent2.method); // true
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Я бы пожалуй использовал это так:

var myModuleNS = extend(myApp, 'modules.module2');
myModuleNS.method = function() {};

//возможно лучше сразу перезаписать прото и не мучиться. 
//Но это опасный некроссбраузерный код.
myModuleNS.__proto__ = {
  method1: function() {},
  publicVar1: 1,
  __proto__: myModuleNS.__proto__
}


Этот способ мне кажется не очень удобным (это так же отмечено в оригинальной статье в следующих строках: "This works exceedingly well when defining purely namespaces alone, but can seem a little less flexible when you want to define both functions and properties at the same time as declaring your namespaces."), я бы пожалуй модифицировал функцую следующим образом:

function extend(ns, ns_string, value) {
    var parts = ns_string.split('.'),
        parent = ns,
        pl, i;

    if (parts[0] == "myApp") {
        parts = parts.slice(1);
    }
    pl = parts.length;

    for (i = 0; i < pl; i++) {
        //create a property if it doesnt exist
        if (typeof parent[parts[i]] == 'undefined') {
            if (value !== undefined && i==pl-1) parent[parts[i]] = value;
            else parent[parts[i]] = {};
        }
        parent = parent[parts[i]];
    }
    return parent;
}


Теперь этим вполне можно пользоваться:
var myModule = extend(myApp, 'modules.myModule', new MyModule());
//это так же подойдет для расширения существующего пространства имен методами
extend(myApp, 'modules.myModule.method', function myNewMethod() {});

Такая конструкция имеет ряд недостатков, например повторная попытка сделать extend myModule, вернет результат первой такой попытки, я бы не ожидал подобного действия от кода.

Конструкция описанная Сергей Мельников , сомнительна, он рекомендует вам с помощью этой функции получать методы искомого модуля. Теперь давайте представим, что запрашиваемого метода не существует - в ответ на extend вы получите пустой объект и попытаетесь его вызвать, а это ой как не понравится программе...

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

function MyModule() {
  var module = extend(NS, 'modules.MyModule', this);
  if (module !== this) return module;
  
  //body of module
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы