#javascript
#javascript
Вопрос:
Я создаю класс часов, и он будет генерировать время каждую секунду.
class Clock {
constructor(template) {
this._template = template;
this._timer = null;
}
render() {
var date = new Date();
var output = this._template
.replace("h", date.getHours())
.replace("m", date.getMinutes())
.replace("s", date.getSeconds());
console.log(output);
}
start() {
this.render();
this._timer = setInterval(this.render, 1000);
}
}
var clock = new Clock("h:m:s");
clock.start();
Поначалу это нормально. Результат такой же, как я ожидаю. Затем появится ошибка
TypeError: Cannot read property 'replace' of undefined
. Это странно. Почему мое template
свойство становится неопределенным?
Комментарии:
1. Где вызывается конструктор часов? похоже, что
template
изначально уже не определено (или, вероятно, становится неопределенным до вызова render).2. @briosheje извините, я должен его отредактировать.
Ответ №1:
Поскольку this.render
это не функция со стрелкой, она потеряет свою this
привязку при использовании через setInterval
.
Либо
- сделайте его функцией со стрелкой (
render = () => { ... }
), или - свяжите его в
setInterval
вызове:this._timer = setInterval(this.render.bind(this), 1000);
Ответ №2:
Вы переходите this.render
к setTimeout
функции и, следовательно, this
контекст изменяется. Вам нужно .bind(this)
и все будет работать так, как ожидалось.
class Clock {
constructor(template) {
this._template = template;
this._time = null;
}
render() {
var date = new Date();
var output = this._template
.replace("h", date.getHours())
.replace("m", date.getMinutes())
.replace("s", date.getSeconds());
console.log(output);
}
start() {
this.render();
this._timer = setInterval(this.render.bind(this), 1000); // <-- here
}
}
new Clock('h:m:s').start();
Комментарии:
1. Или используйте функцию со стрелкой 🙂
2. @NikitaMadeev да, это тоже возможно 😉