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

发布于 2024-10-07 19:49:10 字数 654 浏览 2 评论 0原文

考虑一下:

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

由于 init 函数是这样调用的 (myObj.init),所以我希望 this 是 init 函数中的 myObj。如果是这样的话,为什么 callMe 函数会失败?我该如何在不使用 init 主体中的 this 上下文的情况下调用 callMe 函数? (实际上,通过函数一遍又一遍地使用 this 调用对象方法太烦人了。那么拥有单个对象有什么意义呢?)

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

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

Since the init function gets called this way (myObj.init), I expect this to be myObj in the init function. And if that is the case, why the callMe function fails? How am I supposed to call the callMe function without using the this context in the init body? (Actually, it's too annoying to call the object methods using this over and over again through the functions. So what's the point of having a single object?)

I would like to know how can I fix this so that the callMe method gets called using the first invocation in the code above?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

睫毛溺水了 2024-10-14 19:49:10

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

...这通常是一个坏主意。道格拉斯·克罗克福德 (Douglas Crockford) 可能写了一篇关于为什么这是一个坏主意的更好的描述,您可以找到它此处。基本上,使用 with 几乎不可能知道代码将要做什么(如果您在该 with 中执行任何其他操作,并且会减慢代码的速度) code> 语句不是来自 this 对象)。

这并不是 JavaScript 的 this 与其他一些语言不同的唯一原因。在 JavaScript 中,this 完全由如何调用函数来定义,而不是定义函数的位置。当您执行 this.callMe() (或等效的 this["callMe"]() ,或者当然 foo.callMe()等),发生了两件事:从属性中检索函数引用,并以特殊方式调用该函数以将 this 设置为该属性的对象来自。如果您不以这种方式通过属性调用函数,则调用不会设置任何特定的 this 值,并且您将获得默认值(即全局对象;window 在浏览器上)。调用的行为决定了 this 的含义。我在我的博客上的几篇文章中深入探讨了这一点,此处 和此处

如果您查看 JavaScript 的 callapply 函数(所有函数对象都可用),这一点(没有双关语)会更清楚。如果我这样做:

callMe.call({});

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

所以基本上,只要习惯输入 this 即可。 :-) 即使没有隐式 this 的语法便利(和混乱!),拥有与对象关联的属性和方法仍然很有用。

this is never implicit in JavaScript as it is in some other languages. Although there are ways to do it, like this using the with statement:

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

    // Make `this` implicit (SEE BELOW, not recommended)
    with (this) {
        // Works
        callMe();
    }
},

...it's generally a bad idea. Douglas Crockford probably wrote one of the better descriptions of why it's a bad idea, which you can find here. Basically, using with makes it nearly impossible to tell what the code's going to do (and slows the code down, if you do anything else in that with statement that doesn't come from the this object).

This isn't the only way that JavaScript's this is not the same as it is in some other languages. In JavaScript, this is defined entirely by how a function is called, not where the function is defined. When you do this.callMe() (or the equivalent this["callMe"](), or of course foo.callMe(), etc.), two things happen: The function reference is retrieved from the property, and the function is called in a special way to set this to be the object that property came from. If you don't call a function through a property that way, the call doesn't set any particular this value and you get the default (which is the global object; window on browsers). It's the act of making the call that sets what this is. I've explored this in depth in a couple of articles on my blog, here and here.

This (no pun) can be made even clearer if you look at JavaScript's call and apply functions, which are available on all function objects. If I do this:

callMe.call({});

...it'll call the callMe function with a blank object ({}) as this.

So basically, just get used to typing this. :-) It's still useful to have properties and methods associated with an object, even without the syntactic convenience (and confusion!) of an implicit this.

沒落の蓅哖 2024-10-14 19:49:10

您还可以使用模块模式,它捕获闭包内的所有私有变量,因此您可以在没有 this 的情况下自由使用它们,因为它们位于同一范围。然后,您选择要公开的方法/变量:

var myObj = (function () {
   var init = function () {
      callMe(); // This now works
   };

   var callMe = function () {
      ...
   };

   // Now choose your public methods (they can even be renamed):
   return {
      init: init, // Same name
      callMyName: callMe // Different name
   };
}) ();

现在:

myObj.init(); // Works
myObj.callMyName(); // Works
myObj.callMe(); // Error

You can also use the module pattern, which captures all private variables inside a closure, so you are free to use them without this, as they're in the same scope. You then pick and choose which methods/variables you want to make public:

var myObj = (function () {
   var init = function () {
      callMe(); // This now works
   };

   var callMe = function () {
      ...
   };

   // Now choose your public methods (they can even be renamed):
   return {
      init: init, // Same name
      callMyName: callMe // Different name
   };
}) ();

Now:

myObj.init(); // Works
myObj.callMyName(); // Works
myObj.callMe(); // Error
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文