Это ключевое слово в шаблоне модуля?
Я только начал работать в новой компании и заметил, что во многих их JS мне это кажется совершенно неправильным. Я немного не решаюсь поднять это, не подтверждая, что это неправильно, так как я довольно младший, я не эксперт по JS, и это всего лишь мой второй день, и я не хочу выглядеть глупо.
Поэтому обычно я ожидаю, что шаблон модуля будет выглядеть примерно так:
MODULENAME = MODULENAME || {};
MODULENAME.SUBMODULENAME = (function() {
var bla = {};
bla.somefunction = function() {
//do stuff
};
//add more stuff to bla
return bla;
}());
То, что они имеют по всему своему коду:
MODULENAME = MODULENAME || {};
MODULENAME.SUBMODULENAME = (function() {
var that = this;
that.somefunction = function() {
//do stuff
};
//add more stuff to that
return that;
}());
Теперь, конечно, потому что функция не вызывается как конструктор с new
ключевое слово или как метод, this
связан с window
и они определяют that
как this
, Таким образом, они в основном сбрасывают все в глобальном объекте, и все их имена подмодулей на самом деле являются псевдонимами для window
, Есть ли какая-то причина, по которой кто-то хотел бы сделать это? Или это действительно так неправильно, как мне кажется?
Редактировать:
Я ошибся в постановке var
до определения подмодуля, изначально я написал что-то немного другое и забыл удалить var
, Я также попытался прояснить этот пример, надеюсь, теперь он станет более понятным.
Изменить 2:
Также я посмотрел на скрипты, исполняемые в Firebug, и они определенно добавляют все в window
этот объект - полный беспорядок.
2 ответа
Да, это выглядит неправильно.
MODULENAME = MODULENAME || {}; // missing var
var MODULENAME.SUBMODULENAME = (function() { // probably the missing var from above...
var that = this;
//add some stuff to that
return that; // that is the WINDOW- wrong.
}());
ДЕМО за ущерб, который он может нанести:
var x = function() {
alert('out');
}
var MODULENAME = MODULENAME || {};
MODULENAME.SUBMODULENAME = (function() {
var that = this;
that.x = function() {
alert('DAMAGE');
}
}());
x(); // alert DAMAGE and not "out" - messed up with the global object!
Шаблон модуля используется неправильно, и одна из причин, по которой выражения функций не должны использоваться, когда их использование не обеспечивает ничего, кроме объявления функции. Если целью является создание глобальных функций (в чем я сомневаюсь), то они должны использовать:
function somefuncion() {
...
}
Если их целью является добавление свойств (в данном случае методов) к объекту, что более вероятно, тогда:
MODULENAME.SUBMODULENAME.somemethod = function() { /* do stuff */ };
Если есть необходимость условно создавать методы, например, на основе обнаружения признаков, то может подойти следующее:
(function(global, undefined) {
// In here global is the global object
global.MODULENAME = global.MODULENAME || {};
global.MODULENAME.SUBMODULENAME = global.MODULENAME.SUBMODULENAME || {};
// and undefined is undefined, belt and braces approach
undefined = void 0;
// Direct assignment
function somemethod() {
//do stuff
};
// Assign directly to the "namespace" object
MODULENAME.SUBMODULENAME.somemethod = somemethod;
// Conditional assignment
if ( sometest ) {
MODULENAME.SUBMODULENAME.anothermethod = function(){...};
// Try another way...
} else if (someOtherTest) {
MODULENAME.SUBMODULENAME.anothermethod = function(){...};
// Default
} else {
MODULENAME.SUBMODULENAME.anothermethod = function(){...};
}
// Clean up
global = null;
}(this));
Одна из проблем, связанных с вышеизложенным, заключается в том, что каждая функция, объявленная внутри внешней функции, имеет замыкание обратно на объект функции и его окружение, поэтому она немного расточительна. Гораздо эффективнее сохранять простоту и использовать шаблон модуля только там, где он действительно нужен, и просто использовать простые объявления и назначения функций там, где это не так. Не так весело, но более практично.