Search code examples
javascriptclosuresthisscope

How do the following Javascript functions affect the value of 'this'?


I have an object which has two functions within it, and as I guessed each one has a different value for 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();
            }
        });
    }
},

Then the function is invoked like this:

custom_controls.play_pause()

I've heard that the way you invoke a function denotes the value of this.

So my question is: What is happening here? What kind of function invocations am I using? And how does each one affect this?


Solution

  • When calling obj.func(), this inside the function will be equal to obj. If there is no obj, the global object (window) is used instead. Or if you are running in Strict Mode, undefined is used.

    The first log is your object because you call the function like this:

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

    The second log is window because the function passed as parameter to getIsPlaying is not called with any this:

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

    You can control what the value of this will be when you invoke a function by using call or apply. You can create a new function which will always have the this value set to whatever you want by using the bind function:

    videoPlayer.getIsPlaying(function (video_is_playing) {
            if (video_is_playing) {
    
                console.log(this); // my obj
    
                videoPlayer.pause(true);
            } else {
                videoPlayer.play();
            }
        }.bind(this)); // magic!
    

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