期待JavaScript对象中正确的调用上下文(this)

J R*_*ttz 4 javascript scope this

考虑一下:

window.onload = function () {
    myObj.init();
};

var myObj = {
    init: function () {
        console.log("init: Let's call the callMe method...");

        //callMe is not defined...
        callMe();

        //Works fine!
        this.callMe();
    },

    callMe: function () {
        console.log('callMe');
    }
};
Run Code Online (Sandbox Code Playgroud)

由于init函数以这种方式调用(myObj.init),我希望this在init函数中成为myObj.如果是这种情况,为什么callMe功能失败?如何在callMe不使用init主体中的this上下文的情况下调用该函数?(实际上,this通过函数反复调用对象方法太烦人了.那么拥有单个对象有什么意义呢?)

我想知道如何解决这个问题,以便使用上面代码中的第一个调用来调用callMe方法?

T.J*_*der 8

this从来没有隐含在JavaScript中,就像在其他一些语言中一样.虽然有办法做到这一点,像这样使用with声明:

init: function () {
    console.log("init: Let's call the callMe method...");

    // Make `this` implicit (SEE BELOW, not recommended)
    with (this) {
        // Works
        callMe();
    }
},
Run Code Online (Sandbox Code Playgroud)

......这通常是一个坏主意.道格拉斯克罗克福德可能写了一个更好的描述为什么这是一个坏主意,你可以在这里找到.基本上,使用with几乎不可能告诉代码将要执行的操作(并且如果您在该语句中执行的任何其他内容with不是来自this对象,则会减慢代码速度).

这不是JavaScript this与其他语言不同的唯一方式.在JavaScript中,this完全由函数的调用方式定义,而不是定义函数的位置.当你这样做this.callMe()(或等价this["callMe"](),或者当然foo.callMe()等)时,会发生件事:从属性中检索函数引用,并以特殊方式调用函数以设置this为属性来自的对象.如果您没有通过该属性调用函数,则调用不会设置任何特定this值,您将获得默认值(这是全局对象; window在浏览器上).这是制定电话的行为this是.我已经在我的博客上,在这里这里的几篇文章中深入探讨了这一点.

如果你看一下所有函数对象都可以使用的JavaScript callapply函数,这个(没有双关语)可以更清晰.如果我这样做:

callMe.call({});
Run Code Online (Sandbox Code Playgroud)

...它将callMe使用空白对象({})调用该函数this.

所以基本上,只是习惯打字this.:-)即使没有隐式的语法方便(和混淆!),使对象的属性和方法仍然有用this.