javascript 'this' in ES6 classes return undefined

Doua Beri picture Doua Beri · Jul 8, 2016 · Viewed 19k times · Source

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

Answer

Patrick Roberts picture Patrick Roberts · Jul 8, 2016

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