web-dev-qa-db-ja.com

ES6クラスのjavascript 'this'が未定義を返す

これはスコープの問題だと思いますが、どうすればいいのかわかりません。これが私のコードです: 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()は未定義を出力し、addContentはオブジェクトを出力します。

これを修正するには、フレームがロードされたときにこれに参照を含めることができますか?

ありがとう

9
Doua Beri

.bind()のもう1つの代替方法は、ES6 Arrow関数を使用してコンテキストを保持することです。

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();
11
Patrick Roberts

bind 関数を使用してコンテキストをバインドする

this.frameLoaded.bind(this);

fiddle を参照

6
Max Brodin

ハンドラーをonloadにバインドする必要があります

iframe.onload = function () {
  this.frameLoaded();
}.bind(this);
1
Daniel A. White

新しいスコープを作成しているため、thisコールバック内のonloadはクラスを参照せず、代わりにコールバック関数自体を参照します。 bindframeLoadedメソッドを適切なthisArgに設定する必要があります。

class FrameCreator {

  constructor() {
    this.createFrame();
  }
  createFrame() {
    var iframe = document.createElement('iframe');
    this.iframe = iframe;
    var frameLoaded = this.frameLoaded;
    iframe.onload = frameLoaded.bind(this)
    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();
0
Seth