【问题标题】:How do the following Javascript functions affect the value of 'this'?以下 Javascript 函数如何影响“this”的值?
【发布时间】:2013-11-22 13:10:46
【问题描述】:

我有一个对象,其中有两个函数,我猜每个函数都有不同的 this 值:

custom_controls : {
    play_pause : function () {

        console.log(this); // object

        videoPlayer.getIsPlaying(function (video_is_playing) {
            if (video_is_playing) {

                console.log(this); // window

                videoPlayer.pause(true);
            } else {
                videoPlayer.play();
            }
        });
    }
},

然后函数是这样调用的:

custom_controls.play_pause()

我听说你调用函数的方式表示this 的值。

所以我的问题是:这里发生了什么?我正在使用什么样的函数调用?以及每一项对this有何影响?

【问题讨论】:

  • 我们不知道您是如何调用这些函数的,因为它们是在其他地方调用的。
  • 我不知道你在尝试什么,但如果你想在其他函数中获取this 实例然后var that= this; 然后在其他函数中使用that
  • @KendallFrey 我已经更新了我如何调用该函数的问题。
  • 很好,但它仍然缺少第二个的调用。

标签: javascript closures this scope


【解决方案1】:

当调用obj.func()时,函数内部的this将等于obj。如果没有obj,则使用全局对象 (window)。或者,如果您在Strict Mode 中运行,则使用undefined

第一个日志是您的对象,因为您这样调用函数:

custom_controls.play_pause() // custom_controls will be 'this'

第二个日志是window,因为作为参数传递给getIsPlaying的函数没有被任何this调用:

videoPlayer.getIsPlaying = function(callback) {
  callback(); // this inside callback will be window
}

当您使用callapply 调用函数时,您可以控制this 的值。您可以使用bind 函数创建一个始终将this 值设置为您想要的任何值的新函数:

videoPlayer.getIsPlaying(function (video_is_playing) {
        if (video_is_playing) {

            console.log(this); // my obj

            videoPlayer.pause(true);
        } else {
            videoPlayer.play();
        }
    }.bind(this)); // magic!

参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

【讨论】:

    【解决方案2】:

    每个函数实际上都是在一个上下文中执行的。该上下文表示为您为其调用函数的当前this

    鉴于您的代码: 如果您调用custom_controls.play_pause(),您的意思是“获取名为 play_pause 的对象 custom_controls 的字段并在对象 custom_controls 的上下文中执行它”。

    稍后调用videoPlayer.getIsPlaying() 意味着几乎相同。除了你给它一个回调函数。稍后如何执行该回调函数取决于videoPlayer.getIsPlaying 的实现方式。 如果我必须猜测,我会说 getIsPlaying 在其中某处有一个callback.call(window, video_is_playing)

    call是javascript中所有函数对象的方法。

    如果您想在某些回调中引用this,有几种方法可以解决此“问题”。

    var self = this;
    call_me_maybe(function() {
        console.log(this); //the this that call_me_maybe chose to call your function with
        console.log(self); //the this from the upper scope
    });
    

    或者如果您不关心上下文call_me_maybe 将调用您的函数的对象:

    call_me_maybe((function(){
        console.log(this); //the this from the upper scope
    }).bind(this));
    

    bind 所做的是返回一个函数的 wrap[per],该函数将总是在它所绑定的对象的上下文中被调用。 bind 还可以绑定参数以及函数的 this 对象,创建一种咖喱。

    【讨论】:

      【解决方案3】:

      您的第一个this指的是play_pause

      您的第二个 this 可能是指 Window 或您的 videoPlayer 对象。在 JavaScript 中,闭包和常规函数“通常”附加到 window,调用 this 返回 window。在某些情况下,例如如果您将函数附加到 HTML 元素的点击处理程序,this 指的是元素...

      element.onclick = function(){
        this // -> element
      }
      

      但通常如果你只是创建一个function(),或者有一个像你这样的匿名this 指的是window

      function hello(){
        this // -> window
      }
      

      【讨论】:

        【解决方案4】:

        您发现的 this 是您所期望的对象,因为该函数正在对该对象进行操作。

        我不熟悉您的videoPlayer,但由于this 的值是“窗口”,我想视频播放器A 是浏览器本身的功能,或者B 它的范围是没有正确关闭。

        【讨论】:

          【解决方案5】:

          this指的是函数的“专有”,或者说来自函数的对象是一个方法。

          当你定义一个基本功能时,“专有”就是页面(或窗口)本身。

          您可以查看callback 文档以了解解决方法

          【讨论】:

            【解决方案6】:

            当您调用 videoPlayer.getIsPlaying 时,它会接受回调 fn。回调像cb() 一样直接调用,因此上下文是全局的(窗口)。

            实现在对象上下文中发生的回调。你可以使用

            var fn = cb.bind(customControl);
            videoPlayer.getIsPlaying(fn);    
            

            根据经验,当像object.function 这样调用函数时,它会设置为object。如果直接调用函数,this 设置为窗口。 Function.bind 在绑定object(此值)后返回一个函数,可选地与参数一起。

            阅读:MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-07-01
              • 1970-01-01
              • 1970-01-01
              • 2014-01-18
              • 2017-03-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多