javascript 'this' in ES6 classes return undefined

21,020

Solution 1

Another alternative to .bind() is to use ES6 Arrow function to preserve context:

iframe.onload = () => {
  this.frameLoaded();
};

class FrameCreator {
  constructor() {
    this.createFrame();
  }
  
  createFrame() {
    var iframe = document.createElement('iframe');
    this.iframe = iframe;
    
    iframe.onload = () => {
      this.frameLoaded();
    };

    document.body.appendChild(iframe);
  }
  
  frameLoaded() {
    console.log("frame loaded");
  }
}

class CustomFrameCreator extends FrameCreator {
  addContent() {
    console.log(this); // returns the object
  }
  frameLoaded() {
    console.log(this); // returns the object now
  }
}

var frame = new CustomFrameCreator();
frame.addContent();

Solution 2

Use bind function to bind context

this.frameLoaded.bind(this);

See fiddle

Solution 3

You need to bind the handler for onload

iframe.onload = function () {
  this.frameLoaded();
}.bind(this);
Share:
21,020
Doua Beri
Author by

Doua Beri

Updated on July 30, 2022

Comments

  • Doua Beri
    Doua Beri over 1 year

    I think this is a scope problem, but I'm not sure how to fix this. Here is my code: http://jsfiddle.net/9k9Pe/1498/

    class FrameCreator{
    
        constructor(){
            this.createFrame();
        }
        createFrame(){
          var iframe = document.createElement('iframe');
          this.iframe = iframe;
          var frameLoaded=this.frameLoaded;
          iframe.onload = function () {
                        frameLoaded();
          };
          document.body.appendChild(iframe);
        }
        frameLoaded(){
                console.log("frame loaded");
        }
    }
    
    class CustomFrameCreator extends FrameCreator{
        addContent(){
                console.log(this); // returns the object
        }
        frameLoaded(){
                console.log(this); // returns undefined
        }
    }
    
    var frame=new CustomFrameCreator();
    frame.addContent();
    

    frameLoaded() prints undefined, while addContent prints the object.

    How to fix this, so I can have a reference in this when frame is loaded?

    Thanks

  • frodeborli
    frodeborli over 6 years
    This creates a function that calls the function. I suspect it is not as efficient as bind. Not sure though.
  • Patrick Roberts
    Patrick Roberts over 6 years
    @frodeborli bind() wraps the function internally, anyway, this is how you would implement the polyfill. The part that makes it less efficient is actually the scoped reference to this, which kills some JavaScript optimization potential on the function scope, so you're partially correct, but for the wrong reason.