在JS中拥有正确的'this'值

时间:2010-08-31 15:32:26

标签: javascript this

我有两个类似的Javascript“对象”......

var Object2 = new (function() {
    this.FetchData = function(callback) {
        // do some stuff
        callback(data);
    };
});

var Object1 = new (function() {

    this.DisplayStuff = function() {

    };

    this.LoadData = function() {
        Object2.FetchData(this.OnData);
    };

    this.OnData = function(data) {
        // this == window
        this.DisplayStuff();   // doesn't work
    };

});

当Object1收到OnData的回调时,“this”的值设置为window。 有什么办法可以解决这个问题,以便OnData里面的“this”的值是Object1的实例而不是窗口?

5 个答案:

答案 0 :(得分:5)

框架中常用的一种技术是让调用者决定回调函数的this上下文应该是什么。所以FetchData函数看起来像(感谢@Andy告诉我上下文为null或未定义时的默认范围 - 它是全局对象),

this.FetchData = function(callback, context) {
    callback.call(context, data);
};

调用FetchData时,将Object1作为回调的上下文传递,

Object2.FetchData(this.OnData, this);

另一种选择是使用Function.prototype.bindOnData函数与Object1绑定

Object2.FetchData(this.onData.bind(this));

答案 1 :(得分:3)

这样做的简单方法是在变量中存储 this 的引用,然后使用call()方法:

this.LoadData = function() {
    var self = this;
    Object2.FetchData(function () { self.OnData.call(self) });
};

如果你这么做很多,你可能要考虑在ECMAScript第5版的函数原型上使用 .bind()方法。可以在不受支持的地方实施此方法:

// From Prototype.js
if (!Function.prototype.bind) { // check if native implementation available
  Function.prototype.bind = function(){ 
    var fn = this, args = Array.prototype.slice.call(arguments),
        object = args.shift(); 
    return function(){ 
      return fn.apply(object, 
        args.concat(Array.prototype.slice.call(arguments))); 
    }; 
  };
}

结果函数调用:

this.LoadData = function() {
    Object2.FetchData(this.OnData.bind(this));
};

PrototypeJS - bind()

答案 2 :(得分:0)

基本解决方案是使用apply强制回调上下文。 (或call。不同之处在于参数的传递方式。数组或“正常”)请参阅MDC以获取文档。

答案 3 :(得分:0)

对于回调,你会被“这个”作为窗口(通常)。但是,您可以向Object1添加一个指向自身的成员(很多时候它会调用'self',即“var self = this;”),然后使用它,即self.DisplayStuff()。

答案 4 :(得分:0)

使用javascript,“这个”的模糊性对我来说真的很烦人。所以我尽可能地避免“这个”。我是这样做的:

var Object2 = (function() { // no need for a "new" keyword any more

    var self = {}; // instead of the auto-supplied "this", create my own "self"

    self.FetchData = function(callback) {
        // do some stuff
        callback(data);
    };
    return self; // don't forget to return "self"
});

var Object1 = (function() {

    var self = {}; // instead of the auto-supplied "this", create my own "self"

    self.DisplayStuff = function() {

    };

    self.LoadData = function() {
        Object2.FetchData(this.OnData);
    };

    self.OnData = function(data) {
        self.DisplayStuff();
    };

    return self; // don't forget to return "self"

});

你失去了使用这种技术使用Object.prototype的能力,你失去了使用“instanceof”进行测试的能力,但你永远不必考虑“这个”是什么。