Javascript 具有正确的值';这';在JS中

Javascript 具有正确的值';这';在JS中,javascript,this,Javascript,This,我有两个Javascript“对象”类似于 var Object2 = new (function() { this.FetchData = function(callback) { // do some stuff callback(data); }; }); var Object1 = new (function() { this.DisplayStuff = function() { }; this.LoadD

我有两个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的实例而不是窗口?

基本解决方案是使用
apply
强制回调上下文。(或
调用
。区别在于参数的传递方式。数组或“正常”)请参阅文档。

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

简单的方法是在变量中存储对此的引用,然后使用以下方法:

如果你做了很多,你可能想考虑在EcMAScript第五版的函数原型上使用.bDUE()方法。此方法可在以下不受支持的情况下实施:

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

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

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

Object2.FetchData(this.OnData, this);

另一个选项是使用将
OnData
函数与
Object1
绑定

“this”的模糊性对于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”进行测试的能力,但你永远不必考虑“this”是什么

谁叫Object1.OnData?你把它附在一个活动上了吗?你能告诉我你是如何把它附加到一个事件上的吗?对象2在哪里调用对象1?回调是对象2上的方法之一吗?我希望我能选择两个答案。这是一个很好的响应。不需要
上下文| |窗口
,如果上下文未定义或为空,它将默认为全局对象,在网页的情况下是窗口。@Andy-感谢您为我们指出未指定上下文的默认行为。谢谢@T.斯通-很高兴你喜欢它的舔!像这样的事情正是我所希望的。为什么不让自己这么做呢?这样你就不会失去这些能力了。这也很好。我想我开始这样做是因为我对“这件事”感到愤怒,并且对驱逐它的想法感到兴奋。事实上,这不是真的。我一直在试验Crockford的“寄生遗传”方法,它避开了“这个”。
Object2.FetchData(this.OnData, this);
Object2.FetchData(this.onData.bind(this));
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"

});