Doubt to access this in prototype

Asked

Viewed 58 times

1

I am trying to access some variables within this (Object Orientation) using Object.prototype, but at a certain point I am in doubt if I am doing it correctly:

This and the main function:

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

    this.initPlayer();
};

In this part it’s still okay:

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

Note that I can only access this by using the self = this; this is correct, but when I call the function smartPlayer.prototype. _callTrack(self, track);, I have to pass the self to still be able to access 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 right way for me to access this inside smartPlayer()? For in this way I will always have to be forced to pass self on all functions that are storing some value within this.

I found this problem whenever I pass something among the functions(123).

  • calltrack and a function inside smartplayer?

  • the smartplayer function()

  • Voce cannot use this direct? Or create the var self within the smartplayer function instead of within the prototype?

  • No, because when I use this inside the function that sends a parameter ex: func('array'), this inside the function is like this = array.

1 answer

1


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

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

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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.