Ответ 1
просто инкапсулировать его в TRY/CATCH?
try {
return new TOP.middle.blablabla();
}
catch(err) {
// oh no!
}
return null;
Теперь у меня есть модуль, который следует за длинной цепочкой пространств имен, например:
TOP.middle.realModuleName = function () { /*...*/ }
Мне нужно использовать этот модуль на странице, и я не уверен, включила ли эта страница пространство имен Top.middle. Поэтому я должен был бы сделать что-то вроде:
if (typeof TOP !== 'undefined' && TOP.middle && TOP.middle.realdModuleName) {
new TOP.middle.realModuleName();
}
Я думаю, что инструкция if
выглядит очень длинной и многословной. У кого-нибудь есть предложения по написанию более удобного шаблона проверки параметров для этого случая?
просто инкапсулировать его в TRY/CATCH?
try {
return new TOP.middle.blablabla();
}
catch(err) {
// oh no!
}
return null;
Попробуйте эту простую вспомогательную функцию:
function exists(namespace) {
var tokens = namespace.split('.');
return tokens.reduce(function(prev, curr) {
return (typeof prev == "undefined") ? prev : prev[curr];
}, window);
}
Он принимает вход String
и возвращает объект, если он существует. Вы можете использовать его следующим образом:
var module = exists("TOP.middle.realModuleName");
Например:
exists("noexist"); // returns undefined
exists("window"); // returns DOMWindow
exists("window.innerHeight"); // returns Number
exists("window.innerHeight.toString"); // returns Function
exists("window.innerHeight.noexist"); // returns undefined
Он также корректно работает для выражений, которые вычисляются как false:
testNum = 0;
testBool = false;
testNull = null;
exists("testNum"); // returns 0
exists("testBool"); // returns false
exists("testNull"); // returns null
Я бы попробовал что-то вроде этого, хотя он подвержен ошибкам, если получает некоторый фанковый ввод:
if(check("TOP.middle.realModuleName")) {
//exists
}
//namespace checking function
function check(ns) {
var pieces = ns.split('.'),
current = window;
for(i in pieces) {
if(!(current = current[pieces[i]])) {
return false;
}
}
return true;
}
Вы можете использовать try/catch и искать 'not_defined
':
try {
TOP.middle.realModuleName = function () { /*...*/ };
} catch(e) {
if ( e.type == 'not_defined' ) {
// exception
}
else {
// throw other errors
throw e;
}
}
Вы можете сделать все это в одной строке таким образом:
TOP && TOP.middle && TOP.middle.realdModuleName && new TOP.middle.realdModuleName;
Обратите внимание, что ваша функция будет запущена немедленно. Если вы хотите сохранить функцию для последующего повторного использования, просто назначьте ее (var module =
). Если функция модуля не определена, то undefined
устанавливается/выбрано.
Я использую функцию, которая анализирует пространство имен и создает его, если он не существует. Вот функция:
framework.namespace = function(baseName){
var ns = baseName.split('.');
var o = window;
for (var i=0, l=ns.length; i < l; i++){
o = o[ns[i]] = o[ns[i]] || {};
}
return o;
};
Затем, прежде чем мне нужно использовать пространство имен, я делаю это:
framework.namespace("TOP.middle.realModuleName");
TOP.middle.realModuleName = function(){...};