引用命名空间函数中的所需对象

时间:2010-04-08 18:02:36

标签: javascript namespaces this

当我命名函数时,我无法引用所需的对象。

这里没问题:

obj.test = function() {
  // this == obj
}

但是当我命名空间时,我会被绊倒:

obj.namespace.test = function() {
  // this == namespace
}

在后一个示例中,我知道this引用namespace,但我想引用obj。我该怎么办?

2 个答案:

答案 0 :(得分:1)

没有简单的答案,但您有几个选择:

obj.namespace.test = function () {
  return (function () {
     // this == obj
  }).apply(obj, Array.prototype.slice.call(arguments));
};

这将返回绑定到obj的函数。不幸的是,如果obj被重新分配,这将无效,因为它是一个实时参考。这更加强大:

obj.namespace.test = (function (obj) {
   return function () {
     return (function () {
        // this == obj
     }).apply(obj, Array.prototype.slice.call(arguments));
   };
}(obj));

如你所见,这些都不是很干净。你可能会问自己为什么要依赖this开始。使用obj的常规引用显然是最直接的方法。

答案 1 :(得分:1)

其他人提出了一些很好的建议。

我只想添加你也可以使命名空间成为一个函数,它将返回一个带有指向obj的变量的对象以及你想要的任何成员函数。

示例:

    // Note that "namespace" is a reserved word in JS for some reason,
    //  so you can't use it as a variable/function/etc name.
    var myNamespace = function myNamespace(){
        var that = this;

        var test = function test(){
            //in here use this.that to point to obj
            alert(this.that.name);
        };

        return {that: that, test: test};
    };

    // Then create the obj:
    var obj = { name: "Mr. Ahb Jeckt", myNamespace: myNamespace};

    // Then you can just call the "namespace" and member function like this:
    obj.myNamespace().test();


    //Or, "initialize" the namespace and call it like so:
    obj.myNamespace = obj.myNamespace();
    obj.myNamespace.test();

    obj.name = "Mrs Ahb Jeckt";
    obj.myNamespace.test();

这种方式在“命名空间”本身中没有对obj的硬编码引用,我认为它非常干净。

如果obj是“类”,这也有效;只需使obj成为构造函数而不是对象文字:

// Then create the obj:
var obj = function (name){
    this.name = name || "unnamed";
    this.myNamespace = myNamespace;

    // Initialize the namespace, we can leave this out and just reference
    //    obj.myNamespace() each time as well

    this.myNamespace = this.myNamespace();
};

// Then you can just call the "namespace" and member function like this:

var myObj = new obj("Mr Ahb Jeckt");
myObj.myNamespace.test();

var myObj2 = new obj("Mrs Ahb Jeckt");
myObj2.myNamespace.test();