1

我有以下内容:

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)调用fnwherethis绑定到 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 Obusingfunction并不直观(至少在开始时)。

这就是为什么我试图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可以根据上下文绑定到任何东西)?

4

3 回答 3

3

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

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

第一个参数“范围”是函数内绑定到“this”的对象。因此,以下示例是等效的:

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

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

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

或者您可以修改函数“of”以获取范围参数:

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
}};
于 2009-02-20T14:16:52.243 回答
1

遵循 Douglas Crockford 的简单构造函数模式,我将创建一个使用对象字面量而不是 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
于 2009-02-20T14:13:44.107 回答
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);
于 2009-02-20T15:37:54.653 回答