ES6类中的JavaScript 'this'返回undefined。

13

我认为这是一个作用域问题,但我不确定如何修复它。这是我的代码: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()会打印undefined,而addContent会打印该对象。

如何修复这个问题,以便在帧加载时可以引用它?

谢谢。


2
尝试使用 iframe.onload = () => this.frameLoaded(); - Dan Prince
2
不要这样做,首先绑定它。var frameLoaded=this.frameLoaded; - Kevin B
不清楚您想在 iframe.onload 时运行哪个 frameLoaded 方法,以及使用哪个 this 值。 - Oriol
4个回答

15

另一个替代.bind()的选择是使用ES6箭头函数来保留上下文:

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


这将创建一个调用函数的函数。我怀疑它的效率不如bind。但我不确定。 - frodeborli
@frodeborli bind()会在内部包装函数,这就是你实现polyfill的方式。使其效率降低的部分实际上是对this的作用域引用,它会消耗一些函数作用域的JavaScript优化潜力,所以你部分正确,但原因错误。 - Patrick Roberts

7

使用bind函数绑定上下文。

this.frameLoaded.bind(this);

请查看fiddle

1
你需要绑定onload的处理程序。
iframe.onload = function () {
  this.frameLoaded();
}.bind(this);

0

由于您正在创建新的作用域,因此 onload 回调中的 this 不是指向您的类,而是指向回调函数本身。您必须将您的 frameLoaded 方法 bind 到正确的 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();


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接