Хороший способ проверки пространства имен JavaScript - PullRequest
13 голосов
/ 03 октября 2011

Теперь у меня есть модуль, который следует длинной цепочке пространств имен, например:

TOP.middle.realModuleName = function () { /*...*/ }

Мне нужно использовать этот модуль на странице, и я не уверен, включает ли эта страница пространство имен Top.middle. Поэтому я должен был бы сделать что-то вроде:

if (typeof TOP !== 'undefined' && TOP.middle && TOP.middle.realdModuleName) {
    new TOP.middle.realModuleName();
}

Я думаю, что выражение if выглядит очень длинным и многословным. У кого-нибудь есть предложения о том, как написать более хороший шаблон проверки параметров для этого случая?

Ответы [ 7 ]

7 голосов
/ 04 октября 2011

Попробуйте эту простую вспомогательную функцию:

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
6 голосов
/ 03 октября 2011

просто заключить его в TRY / CATCH?

try {
    return new TOP.middle.blablabla();
}
catch(err) {
    // oh no!
}

return null;
2 голосов
/ 03 октября 2011

Вы можете использовать try / catch и искать 'not_defined':

try {
    TOP.middle.realModuleName = function () { /*...*/ };
} catch(e) {
    if ( e.type == 'not_defined' ) {
        // exception
    }
    else {
        // throw other errors
        throw e;
    }
}
2 голосов
/ 03 октября 2011

Я бы попробовал что-то вроде этого, хотя это может привести к ошибке, если он получит какой-то броский ввод:

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;
}
0 голосов
/ 07 июля 2018

Краткий ответ

То, как я это узнал ( относится и к созданию пространства имен ):

// Check if the com namespace does not exist:
if (!com) {
    var com = {};
}

// Check if your namespace does not exist:
if (!com.myNamespace) {
    var com.myNamespace = {};
}
<Ч />

Некоторая информация, которую я узнал (пока)

Согласно книге, которую я читаю, пространство имен com является контейнером для коммерческих продуктов (я имею в виду веб-сайты, библиотеки и т. Д.).

Пространство имен изначально было создано для хранения доменов. Тем не менее, сегодня вы найдете com.* в библиотеках, базах данных или даже в фреймворках!

В настоящее время он управляется VeriSign и существует в течение 33 лет сейчас!

<Ч />

Длинный ответ

Во-первых, нам нужно убедиться, что пространство имен main существует. Мы сделаем эту проверку, если com не существует:

if (!com) {
    var com = {};
}

com - наиболее распространенное пространство имен для проверки. Однако мы можем проверить любое пространство имен.

Мы могли бы пропустить эту часть, но было бы действительно раздражающим, чтобы смешать все ваши функции.

Если com не существует, создайте его.

var com = {};

Наконец, нам нужно проверить, существует ли myNamespace. Мы будем использовать тот же метод для com, но на этот раз мы добавим com. до myNamespace.

if (!com.myNamespace) {
    var com.myNamespace = {};
}

Причина, по которой мы добавляем com. перед объявлением пространства имен, заключается в том, что пространство имен com создается на втором уровне , а myNamespace - на третьем уровне.

Я рекомендую вам добавить пространство имен четвертого уровня для вашего проекта.
Это гарантирует, что:

  • у вашего проекта есть свое пространство имен (если занято myNamespace).

  • ваш проект не будет смешиваться с другими проектами (например, com.projectA.other и com.projectA.yourProject ).

  • Ваши функции не будут перепутаны (например, у вас есть функция с именем write).

<Ч />

Теперь ваш код

Ты почти у цели! Вот как это выглядело бы I :

if (!TOP) {
    // Reinitialize your TOP Namespace here:
    var TOP = {};
}

if (!TOP.middle) {
    // Reinitialize your MIDDLE Namespace here:
    var TOP.middle = {};
}

if (typeof TOP.middle.realModuleName == "function") {
    new TOP.middle.realModuleName ();
}
else {
    // Redefine your function here (you never know ;) )
}
0 голосов
/ 03 октября 2011

Я использую функцию, которая анализирует пространство имен и создает его, если оно не существует. Вот функция:

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(){...};
0 голосов
/ 03 октября 2011

Вы можете сделать все это в одной строке следующим образом:

TOP && TOP.middle && TOP.middle.realdModuleName && new TOP.middle.realdModuleName;

Обратите внимание, что ваша функция будет запущена немедленно. Если вы хотите сохранить функцию для последующего повторного использования, просто назначьте ее (var module =). Если функция модуля не определена, то undefined устанавливается / выбрасывается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...