如何以编程方式将函数添加到嵌套命名空间?

时间:2011-01-11 14:46:26

标签: javascript

假设我有这个函数,当我只是传递一个字符串时,动态创建我的命名空间,(我很确定YUI JS库基本上是这样做的):

MyObj.namespace('fn.method.name');

会导致

MyObj.fn.method.name = {}

正在创建 - 所有三个级别都等同于一个空对象。

现在,我想要做的是将最后一级(在本例中为name)设置为一个函数,但不必重新声明新创建的对象。
所以不要这样做:

function fnName() { /* some code here */ }
MyObj.namespace('fn.method.name');
MyObj.fn.method.name = new fnName();

我想打电话给:

MyObj.add('fn.method.name', fnName);

在内部,add方法将以编程方式实例化传入的函数:

MyObj.fn.method.name = new fnName()

在我实现它的方式中,我可以创建命名空间对象并将其设置为空对象,但是,当我尝试实例化传入的函数并将该命名空间与传入的函数关联时,它永远不会被添加到命名空间。相反,始终返回一个空对象。有什么想法吗?

编辑:这是namespace方法。这作为JSON对象附加到基础对象,因此请忽略格式:

namespace: function (ns) {
    var _ns = ns.split('.'), 
        i = 0, nsLen = _ns.length,
        root = this;
    if (_ns[0] === gNS) {
        _ns.shift();
            nsLen = _ns.length;
        }
        for (i = 0; i < nsLen; i++) { 
            // create a property if it doesn't exist 
            var newNs = _ns[i];
            if (typeof root[newNs] === "undefined") {
                root[newNs] = {};
            }
            root = root[newNs];
        }
        return root;
    }

edit2 - 删除了传入的fn参数

3 个答案:

答案 0 :(得分:1)

你在寻找这样的东西:

var root = {};

function create(ns, fn) {
   var nsArray = ns.split(/\./);
   var currentNode = root;

   while(nsArray.length > 1) {
      var newNS = nsArray.shift();

      if(typeof currentNode[newNS] === "undefined") {
         currentNode[newNS] = {};
      }

      currentNode = currentNode[newNS];
   }

   if(fn) {
      currentNode[nsArray.shift()] = fn;
   }

   else {
      currentNode[nsArray.shift()] = {};
   }
}

然后:

create("a.b.c");

console.log(root.a);
console.log(root.a.b);
console.log(root.a.b.c);

给出:

Object { b={...}}
Object { c={...}}
Object {}

create("d.e.f", function() { console.log("o hai"); });

console.log(root.d);
console.log(root.d.e);
console.log(root.d.e.f);

给出:

Object { e={...}}
Object {}
function()

调用您定义的函数:

root.d.e.f();

给出:

o hai

答案 1 :(得分:0)

你还没有给出命名空间功能,但你的添加功能看起来像这样:

MyObj.add = function (namespace, value) {

    var names = namespace.split('.'), current = this, name;

    while (names.length > 1) {

        name = names.shift();
        current[name] = {};
        current = current[name];

    }

    current[names[0]] = value;

};

此代码分配给予命名空间最后一部分的值。如果你想要传入函数构造的对象(并假设构造函数不带参数),你可以将它修改为current[names[0] = new value();

答案 2 :(得分:0)

function ns() {
    var root = window;

    for (var i = 0; i < arguments.length; i++) {
        var arr = arguments[i].split(/\./);

        for (var j = 0; j < arr.length; j++) {
            var item = arr[j];

            if (typeof item !== 'string') {
                root = item;
            } 
            else {
                if (!root[item]) {
                    root[item] = {};
                }
                root = root[item];
            }
        }
        root = window;
    }
}

然后您可以使用

创建
ns('fn.method.name');

ns('fn.method.name','fn.method.secondName');

并使用

致电
fn.method.name

此函数在'window'上创建命名空间,因此您也可以使用

window.fn.method.name