更好的检查JavaScript命名空间的方法

时间:2011-10-03 18:48:18

标签: javascript namespaces

现在我有一个跟随长链名称空间的模块,例如:

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

我需要在页面上使用此模块,我不确定此页面是否包含名称空间Top.middle。所以我必须做类似的事情:

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

我认为if语句看起来很冗长且冗长。任何人都有关于如何为这种情况编写更好的参数检查模式的建议吗?

7 个答案:

答案 0 :(得分:7)

尝试这个简单的辅助函数:

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

答案 1 :(得分:6)

只是将其封装在TRY / CATCH中?

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

return null;

答案 2 :(得分:2)

我会尝试类似这样的东西,但如果它收到一些时髦的输入则很容易出错:

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;
}

答案 3 :(得分:2)

您可以使用try / catch查找“not_defined”:

try {
    TOP.middle.realModuleName = function () { /*...*/ };
} catch(e) {
    if ( e.type == 'not_defined' ) {
        // exception
    }
    else {
        // throw other errors
        throw e;
    }
}

答案 4 :(得分:0)

你可以用这种方式完成整个事情:

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

请注意,您的功能将立即运行。如果要存储该函数以供以后重用,只需指定它(var module =)。如果未定义模块功能,则设置/丢弃undefined

答案 5 :(得分:0)

我使用一个解析命名空间的函数,如果它不存在则创建它。这是功能:

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(){...};

答案 6 :(得分:0)

简短答案

我的学习方式(同样适用于名称空间的创建):

// 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是在第三层进行的。 / p>

  

我建议您为项目添加第四级名称空间。
  这样可以确保:

     
      
  • 您的项目具有它的拥有名称空间(如果使用了myNamespace)。

  •   
  • 您的项目不会与其他项目(例如com.projectA.other和 com.projectA.yourProject )混合在一起。

  •   
  • 您的函数不会混淆(例如,您有一个名为write的函数)。

  •   

现在,您的代码

您快到了!这是的看法:

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 ;) )
}