#javascript #design-patterns
#javascript #шаблоны проектирования
Вопрос:
Я пытаюсь лучше организовать свой JavaScript. Моя цель — иметь модульную архитектуру, которую я могу разбить на отдельные файлы (sitename.js , sitename.utils.js и т.д.).
Я хотел бы знать, каковы преимущества и недостатки этих двух шаблонов и какой из них больше подходит для разбиения на модули, которые находятся в отдельных файлах.
ШАБЛОН # 1 (шаблон модуля)
var MODULE = (function () {
//private methods
return {
common: {
init: function() {
console.log("common.init");
}
},
users: {
init: function () {
console.log("users.init");
},
show: function () {
console.log("users.show");
}
}
}
})();
ШАБЛОН # 2 (одноэлементный)
var MODULE = {
common: {
init: function() {
console.log("common.init");
}
},
users: {
init: function() {
console.log("users.init");
},
show: function() {
console.log("users.show");
}
}
};
Комментарии:
1. Первое, что приходит на ум, это то, что шаблон 1 допускает код инициализации, который может включать объявления переменных или функций, которые немедленно выходят за пределы области видимости, таким образом, не загрязняя окружающую область видимости.
Ответ №1:
Лично я рекомендую расширение # 1 следующим образом:
var Module = (function(Module) {
// A comment
Module.variable1 = 3;
/**
* init()
*/
Module.init = function() {
console.log("init");
};
// ...
return Module;
})(Module || {});
Мне нравится этот шаблон по нескольким причинам. Во-первых, документация (в частности, в стиле javadoc) выглядит более естественно, когда все ваши функции являются объявлениями, а не большим хэшем. Во-вторых, если ваши подмодули увеличиваются в размерах, это позволяет разбивать их на несколько файлов без какого-либо рефакторинга.
Например, модуль if.Пользователи должны были перейти в свой собственный файл:
var Module = Module || {};
Module.Users = (function(Users) {
/**
* init()
*/
Users.init = function() {
console.log("Module.Users.init");
};
// ...
return Users;
})(Module.Users || {});
Теперь «module.js » и «module.users.js » это могут быть отдельные файлы, и они будут работать независимо от порядка их загрузки. Также обратите внимание на локальную область действия имени модуля — это очень удобно, если имя вашего модуля длинное, потому что вы можете взять «MyApp.Users.EditScreen» и ссылаться на него с помощью переменной типа «ES» в рамках определения вашего модуля.
Комментарии:
1. Новый шаблон также позволяет дополнять модуль другими способами. На этом сайте есть действительно хорошая статья о модулях javascript
2. Это хорошо, но я получаю сообщение об ошибке — jsfiddle.net/rjFHB или, возможно, я инициализирую модуль. Пользователи в неправильном направлении.
3. Это была моя ошибка — «Модуль. Пользователи»не должны иметь var перед ним (поскольку глобальный модуль уже определен). Я отредактирую это.
Ответ №2:
Первый шаблон допускает использование частных переменных, методов и т. Д. Через замыкания. Например:
var MODULE = (function () {
var privateStuff = 'This is private';
var doStuff = function(obj) {
console.log('Doing stuff...');
console.log(privateStuff);
};
return {
common: {
init: function() {
console.log("common.init");
doStuff(this);
}
},
users: {
init: function () {
console.log("users.init");
},
show: function () {
console.log("users.show");
}
}
}
})();
privateStuff
и doStuff
не являются свойствами объекта и не доступны ни для чего, кроме того, что определено внутри возвращаемой функции MODULE
. Итак, показать пример того, как это сделать с помощью # 2, невозможно.
В JS нет понятия закрытых членов, поэтому вы не можете определить их через обычный объектный литерал. Так что, если вам нужны личные вещи, выбирайте первый вариант. Однако, если вы этого не сделаете, # 2 проще.
Ответ №3:
Ваш написанный код практически такой же. Однако с первой формой намного проще работать по мере развития вашего кода, потому что она позволяет добавлять частные переменные и функции. Вторая форма не поддерживает это, и в конечном итоге вы почти всегда хотите получить первую форму.