Ответ 1
Правильный ответ здесь, конечно же, заключается в следующем: "это зависит".
Если вы полностью согласны со всеми данными и всеми методами, для каждого раздела вашего сайта на 100% общедоступным, то просто используя единственный литерал (или несколько литералов), с вложенными объектами, если это необходимо, полностью прекрасен, предполагая что вы можете удержать его от превращения в один гигантский шар кода.
Если вам нужно какое-либо частное состояние, которое имеет какое-либо постоянство (т.е. не reset каждый раз, когда вы запускаете какую-либо функцию), то раскрывающий модуль отлично работает.
Это сказало:
Это не требование раскрывающего модуля для вас иметь метод .init
вообще.
Если ваш модуль может быть автономным, просто сосредоточьтесь на экспорте того, что вам хотелось бы обнародовать.
С этой целью, когда я пишу код, на который может обратить внимание команда, позже я обнаруживаю, что создаю объект public_interface
и возвращаю его (именованная версия анонимного объекта, который вы возвращаете).
Преимущество этого минимально, за исключением добавления понимания того, что все, что должно быть сделано публичным, должно быть добавлено к интерфейсу.
Способ, которым вы сейчас пользуетесь:
var module = (function () { /* ... */ return {}; }());
module.submodule = (function () { /*...*/ return {}; }());
Не лучше или хуже, чем литералы, потому что вы можете так же легко сделать это:
var module = {
a : "",
method : function () {},
meta : { }
};
module.submodule = {
a : "",
method : function () {},
meta : { }
};
Пока вы не нажмете что-то, что не работает для вас, работайте с тем, что наполняет ваши потребности.
Лично я обычно создаю любые объекты только для данных как литералы: config-objects, объекты, которые входят в другие соединения и т.д.
Любой простой объект, который требует, может быть, один или два метода, и может быть построен путем вложения только одного или двух уровней в глубину, я мог бы построить буквально (пока он не требует инициализации).
// ex:
var rectangle = {
width : 12,
height : 24,
area : 0,
perimeter : 0,
init_area : function () { this.area = this.width * this.height; return this; }, // buh...
init_perimeter : function () { this.perimeter = (this.width * 2) + (this.height * 2); return this; } // double-buh...
}.init_area().init_perimeter();
Если мне нужно несколько из них, возможно, я создам конструктор.
Но если бы мне только понадобилось одно из таких уникальных, как это, разве это не избавило бы меня от некоторых головных болей, чтобы просто сделать что-то вроде этого:
var rectangle = (function (width, height) {
var public_interface = {
width : width,
height : height,
area : width * height,
perimeter : (2 * width) + (2 * height)
};
return public_interface;
}(12, 24));
Если потребовалось более продвинутое вычисление, я мог бы держать любые лишние вары частными и работать над ними изнутри.
Если мне нужно иметь конфиденциальные данные внутри объекта и функции для работы с этими данными, тогда у меня могут быть публичные функции, которые вызывают эти частные функции и возвращают результаты, а не предоставляют доступ.
Кроме того, если я реорганизую свой код и решаю переименовать rectangle
в какой-то момент, то любые функции, вложенные в 3 или более глубинные, которые ссылаются на rectangle
, также должны быть изменены.
Опять же, если вы структурируете свои методы, так что им не нужно напрямую запрашивать какой-либо объект, который больше, чем this
, тогда у вас не будет этой проблемы...
... но если у вас есть интерфейс, который выглядит так:
MyApp.myServices.webService.send();
и он ожидает найти:
MyApp.appData.user.tokens.latest; // where personally, I might leave tokens in a closure
Если вы измените структуру своего модуля appData, у вас будут всевозможные ошибки в вашем модуле webService, пока вы не найдете все ссылки на старый формат и не переименуете их все.