如何在其成员函数中引用对象?

时间:2009-02-20 14:01:20

标签: javascript oop this

我有以下内容:

var o = {f: function(fn) {
    fn.call(o);
}};
var ob = {f: function() {
    o.f(function() {
        this.x = 2; //HERE: how can this reference ob?
        //ob.x = 2;
    });
}};
ob.f();
ob.x; // undefined

o.f(fn)调用fn,其中this绑定到o。

在HERE,我想使用this来访问ob。 但是,在调用ob.f时,this绑定到o。 我认为JQuery就是这样的。 例如:

$(...).blah(function() {
    this // this is bound to $(...) jquery object.
    ...
};

我现在正在做的是:

var Ob = function() {
    var self = this;
    self.f = function() {
        o.f(function() { self.x = 2; };
    };
};
var ob = new Ob();
ob.f();
ob.x; // 2

但我不喜欢上面因为文体原因:

  1. 使用new运算符听起来像是经典的OOP。
  2. 使用class Ob定义function并不直观(至少在开始时)。
  3. 这就是我试图用对象文字定义ob的原因。 但我找不到在函数中引用对象ob的方法 使用方法调用将this设置为ob以外的其他对象。

    我可以做以下事情:

    var ob = {f: function() {
        o.f(function() {
            self.x = 2;
        });
    }};
    var self = ob;
    ob.f();
    ob.x;
    

    但我不知道如何考虑因素。 我试过了:

    function obj(o) {
        return function() {
            var self = o;
            return o;
        }();
    }
    var ob = obj({f: function() {
        o.f(function() {
            self.x = 2;
        });
    }});
    ob.f();
    ob.x;// ReferenceError: self is not defined
    

    那么,有没有办法在对象内的函数中引用对象 可靠(this可以绑定任何东西,具体取决于上下文)?

3 个答案:

答案 0 :(得分:3)

在JavaScript中,函数是对象,有两种方法可以调用函数:

call(scope, arg1, arg2, ...);
apply(scope, args);  // args is an array of arguments to call the function with

第一个参数'scope'是在函数中绑定到'this'的对象。因此,以下示例是等效的:

obj.method(1, 2, 3);
obj.method.call(obj, 1, 2, 3);
obj.method.apply(obj, [1, 2, 3]);

在第一个示例中,您使用'o'作为范围调用传递给o.f()的函数:

var o = {f: function(fn) {
    fn.call(o);
}};

因此,你的函数传入'ob'引用'o',如下所示:

var ob = {f: function() {
    o.f(function() {
        this.x = 2; //HERE: how can this reference ob?
        //ob.x = 2;
    });
}};

在“HERE”行中,“this”实际上是“o”。

您可以尝试以下方法:

var ob = {f: function() {
    var self = this;
    o.f(function() {
        self.x = 2; // self is ob now
    });
}};

或者您可以修改函数'o.f'以获取范围参数:

var o = {f: function(fn, scope) {
    fn.call(scope || this); // Uses the given scope or this (= 'o') if no scope is provided
}};

然后你可以在'ob'中传递'this':

var ob = {f: function() {
    o.f(function() {
        this.x = 2; // 'this' will be the 'outer' this
    }, this); // Here: this as scope
}};

答案 1 :(得分:1)

遵循Douglas Crockfords简单的构造函数模式,我会创建一个使用对象文字而不是new的构造函数。像这样:

var o = {f: function(fn) {
    fn.call(o);
}};

function obj() {
    var me = {};
    me.f = function () {
        o.f(function() {
            me.x = 2;
        });
    };
    return me;
}

var ob = obj();
ob.f();
ob.x; // 2

答案 2 :(得分:0)

你可以在没有辅助功能的情况下完成,只需使用文字:

var o = {f: function(fn) {
    fn.call(o);
}};
var ob = {f: function() {
    var self = this; // this == ob
    o.f(function() {
        self.x = 2; // self == enclosing function's this == ob
    });
}};
ob.f();
assert(ob.x == 2);