使用回调方法将 JavaScript 函数转换为 class

Convert JavaScript function to class with callback methods

我正在尝试将以下函数转换为 JavaScript 中的 class(来自 CMS created here 的原始函数),

function Countdown(options) {
  var timer,
  instance = this,
  seconds = options.seconds || 10,
  updateStatus = options.onUpdateStatus || function () {},
  counterEnd = options.onCounterEnd || function () {};

  function decrementCounter() {
    updateStatus(seconds);
    if (seconds === 0) {
      counterEnd();
      instance.stop();
    }
    seconds--;
  }

  this.start = function () {
    clearInterval(timer);
    timer = 0;
    seconds = options.seconds;
    timer = setInterval(decrementCounter, 1000);
  };

  this.stop = function () {
    clearInterval(timer);
  };
}

有了这个用法,

var myCounter = new Countdown({  
    seconds:5,  // number of seconds to count down
    onUpdateStatus: function(sec){console.log(sec);}, // callback for each second
    onCounterEnd: function(){ alert('counter ended!');} // final action
});

myCounter.start();

我的尝试是,

Countdown: class {
    constructor(options) {
        this.seconds = options.seconds || 10;
        this.updateStatus = options.onUpdateStatus || function () { };
        this.counterEnd = options.onCounterEnd || function () { };
        this.instance = this;
        this.timer = null;
    }

    decrementCounter() {
        this.updateStatus(this.seconds);
        if (this.seconds === 0) {
            this.counterEnd();
            this.instance.stop();
        }
        this.seconds--;
    }

    start() {
        clearInterval(this.timer);
        this.timer = 0;
        this.timer = setInterval(this.decrementCounter, 1000);
    }

    stop () {
        clearInterval(this.timer);
    }
}

然后这样称呼它,

var counter = new Countdown({  
    seconds:5,  // number of seconds to count down
    onUpdateStatus: function(sec) {
        $("#timer").text(sec);
    }, // callback for each second
    onCounterEnd: function() {
        closeModal();
    } // final action
});
counter.start();

它在 decrementCounter()

中抛出此错误

Uncaught TypeError: this.updateStatus is not a function

我做错了什么?

this 指的是没有 updateStatus 的全局对象,因为 setInterval 函数不保留 this-上下文。

在构造函数中使用bind修复它:

Bind creates a new function that will have this set to the first parameter passed to bind().

constructor(options) {
    this.seconds = options.seconds || 10;
    this.updateStatus = options.onUpdateStatus || function() {};
    this.counterEnd = options.onCounterEnd || function() {};
    this.instance = this;
    this.timer = null;

    this.decrementCounter = this.decrementCounter.bind(this);
  }

在 javascript classes 中,如果您使用常规的旧函数 functionName() { } 该函数无法访问 class 中的 this他们有自己的功能 this。您必须手动将 this 绑定到构造函数中的该函数才能访问 classes this.

contructor() {
  this.decrementCounter = this.decrementCounter.bind(this);
}

如您所见,这将很快变得重复,因为您必须对 class 中的每个方法执行此操作。为此,您可以使用 es6 箭头函数。

decrementCounter = () => {}

es6 箭头函数自动将 this 绑定到其父范围,以便您可以在方法内部访问父 this

我的解释不准确,但就是这样。

当我找到一个更好的解释时,我会附上一个link。