Doubt to access this in prototype

1

I'm trying to access some variables within this (Object Orientation) using Object.prototype, but at some point I'm in doubt if I'm doing the right thing:

This is the main function:

function smartPlayer(){
    this.trackCurrentInfo;
    this.tracksList;
    this.trackCurrentList;
    this.teste = "Esta tudo ok";

    this.initPlayer();
};

In this part everything is still ok:

smartPlayer.prototype.initPlayer = function(){
    var self = this;

    /* Event button play */
    playMusic.addEventListener("click", function(){
        if (self.trackCurrentInfo === undefined) {
            self.trackList = getDailyrMusic();
            self.trackCurrentList = 0;
        }

        var track = self.trackList[self.trackCurrentList];
        smartPlayer.prototype._callTrack(self, track);
    });
}

Notice that I can only access this, using self = this; This is the correct one, but when I call the smartPlayer.prototype._callTrack (self, track) function, I have to pass the self to still get access to this of the main function that is: smartPlayer (); .

Within this function I have the following:

smartPlayer.prototype._callTrack = function(self, array){
    /* set current Track infos */
    this.trackCurrentInfo = {
        "trackAlbumId": array.trackId,
        "trackMusic": array.trackName,
        "trackArtist": array.trackArtist,
        "trackAlbum": array.trackAlbum,
        "trackAlbumCover": array.trackCover,
        "trackCurrentTime": 0,
        "trackFullTime": array.trackDuration
    };

    // update elements
    // console.log(this.trackCurrentInfo)
    trackMusic.innerHTML = self.trackCurrentInfo.trackMusic;
    trackArtist.innerHTML = self.trackCurrentInfo.trackArtist;
    trackAlbum.innetHTML = self.trackCurrentInfo.trackAlbum;

}

Would this be the correct way I could access this within smartPlayer ()? For in this way I will always have to pass the self on all the functions that are storing some value within this.

I encountered this problem every time anything goes through the functions (123).

    
asked by anonymous 12.08.2017 / 19:48

1 answer

1

The problem is generated by the nature of the addEventListener method. When it calls the callback you pass it the execution context changes (ie: this). You have several ways to resolve this:

  • using arrow functions
  • using .call , .apply , .bind
  • using ES6 classes

Examples:

With arrow function:

smartPlayer.prototype.initPlayer = function(){

    /* Event button play */
    playMusic.addEventListener("click", () => { // <---- repara aqui!
        if (this.trackCurrentInfo === undefined) {
            this.trackList = getDailyrMusic();
            this.trackCurrentList = 0;
        }

        var track = this.trackList[this.trackCurrentList];
        this._callTrack(track);
    });
}

With .bind :

smartPlayer.prototype.initPlayer = function(){
    var self = this;

    /* Event button play */
    playMusic.addEventListener("click", function(){
        if (this.trackCurrentInfo === undefined) {
            this.trackList = getDailyrMusic();
            this.trackCurrentList = 0;
        }

        var track = this.trackList[this.trackCurrentList];
        this._callTrack(self, track);
    }.bind(this)); // <------ repara aqui!
}

Using ES6:

class smartPlayer {
  constructor() {
    /* Event button play */
    playMusic.addEventListener("click", this.playTrack.bind(this));
  }
  playTrack(nr) {
    if (this.trackCurrentInfo === undefined) {
      this.trackList = this.getDailyrMusic();
      this.trackCurrentList = 0;
    }

    var track = this.trackList[this.trackCurrentList];
    this._callTrack(track);
  }

  getDailyrMusic() {
    // algo...
  }
  _callTrack(self, array) {
    /* set current Track infos */
    this.trackCurrentInfo = {
      "trackAlbumId": array.trackId,
      "trackMusic": array.trackName,
      "trackArtist": array.trackArtist,
      "trackAlbum": array.trackAlbum,
      "trackAlbumCover": array.trackCover,
      "trackCurrentTime": 0,
      "trackFullTime": array.trackDuration
    };

    // update elements
    // console.log(this.trackCurrentInfo)
    trackMusic.innerHTML = this.trackCurrentInfo.trackMusic;
    trackArtist.innerHTML = this.trackCurrentInfo.trackArtist;
    trackAlbum.innetHTML = this.trackCurrentInfo.trackAlbum;
  }
}
    
12.08.2017 / 20:49