Конвертировать функцию JavaScript в класс с помощью методов обратного вызова - PullRequest
3 голосов
/ 20 сентября 2019

Я пытаюсь преобразовать следующую функцию в класс в JavaScript (исходная функция из CMS создана здесь ),

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 не является функцией

Что я делаю не так?

Ответы [ 2 ]

5 голосов
/ 20 сентября 2019

this относится к глобальному объекту, который не имеет updateStatus, потому что функция setInterval не сохраняет this -контекст.

Использование bind в конструкторе, чтобы исправить это:

Bind создает новую функцию, в которой this будет установлен первый параметр, переданный 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);
  }
1 голос
/ 20 сентября 2019

В классах javascript, если вы используете обычную старую функцию functionName() { }, функция не имеет доступа к this класса внутри функции, поскольку они имеют свои собственные this.Вам нужно будет вручную связать this с этой функцией внутри конструктора, чтобы иметь доступ к классам this.

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

. Как вы можете видеть, это станет повторным, как только вам придется делать это длякаждый метод внутри класса.Чтобы помочь с этим, вы можете использовать es6 функции стрелок.

decrementCounter = () => {}

es6 функция стрелок автоматически связывает this со своей родительской областью, так что вы можете получить доступ к родителям this внутри методов.

Мое объяснение не точное, но оно выглядит следующим образом.

Я приложу ссылку к более подробному объяснению, когда найду его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...