На данный вопрос уже ответили:
Вопрос такой:Почему в функциональном стиле в setInterval render вызывается как обычно, а в прототипном используется вызов через замыкание?
И есть ли смысл использовать метод bind вместо замыкания через новую переменную self?
Код в функциональном стиле.: function Clock(options) {
var template = options.template;
var timer;
function render() {
var date = new Date();
var hours = date.getHours();
if (hours < 10) hours = '0' + hours;
var min = date.getMinutes();
if (min < 10) min = '0' + min;
var sec = date.getSeconds();
if (sec < 10) sec = '0' + sec;
var output = template.replace('h', hours).replace('m', min).replace('s', sec);
console.log(output);
}
this.stop = function() {
clearInterval(timer);
};
this.start = function() {
render();
timer = setInterval(render, 1000);
Тот же код в прототипном стиле:
function Clock(options) {
this._template = options.template;
}
Clock.prototype._render = function render() {
var date = new Date();
var hours = date.getHours();
if (hours < 10) hours = '0' + hours;
var min = date.getMinutes();
if (min < 10) min = '0' + min;
var sec = date.getSeconds();
if (sec < 10) sec = '0' + sec;
var output = this._template.replace('h', hours).replace('m', min).replace('s', sec);
console.log(output);
};
Clock.prototype.stop = function() {
clearInterval(this._timer);
};
Clock.prototype.start = function() {
this._render();
var self = this;
this._timer = setInterval(function() {
self._render();
}, 1000);
};
Касательно первой части вопроса, почему нельзя при прототипном стиле использовать this._timer = setInterval(this._render, 1000)
.
function A() {
let instanceVariable = 1;
function _render() {
console.log("Rendring A...");
console.log(instanceVariable);
}
this.start = function() {
setInterval(_render, 1000);
}
}
function B() {
this.instanceVariable = 1;
}
B.prototype._render = function() {
console.log("Rendering B...");
console.log(this.instanceVariable);
}
B.prototype.start = function() {
setInterval(this._render, 1000);
}
new A().start();
new B().start();
Причина проста: потеря контекста. Можно видеть из примера с функцией B
, что _render
хотя и вызывается и нормально отрабатывает, но поскольку вызвана она в контексте глобального (в данном случае) объекта, то инстансную переменную внутри этой функции не видно.
Происходит так потому, что функции setInterval
мы передали в качестве первого параметра функцию, которую хотим вызывать раз в секунду, то есть, грубо говоря, сам код функции. А о контексте setInterval
ничего в момент вызова знать не будет.
Именно поэтому в вашем примере используется такая конструкция:
var self = this;
this._timer = setInterval(function() {
self._render();
}, 1000);
Сначала сохраняется контекст, а потом функция _render
вызывается уже непосредственно в правильном контексте.
Подобный подход на самом деле уже устаревший, и сейчас наилучшим решением будет воспользоваться стрелочной функцией:
// var self = this; // закомментировано, явно сохранять контекст более нет необходимости
this._timer = setInterval(() => { // стрелочная функция
this._render(); // теперь здесь используем `this`
}, 1000);
Может быть дело в том,что при прототипмном наследовании мы теряем возможность использовать локальные переменные как приватные свойства, у них больше нет общей области видимости с конструктором.По этому в функциональном наследовании мы не потеряем контекст при вызове метода render,он не ссылается на this,а в прототипном варианте render() ссылается на this._template. и из-за этого нужно привязывать контекст вызова, что мы и делаем через переменную self и метод apply. ведь при использовании setInterval контекст вызова теряется. Короче я походу бред тут сморозил)
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
хочу реализовать перемещение всех блоков на JS, те нажал на один квадрат вместе с ним перемещаются другие
Не могу понять, почему не работает получение json ответа для историй для такой ссылки:https://iinstagram
Такой возник вопрос: хочу внутри рекурсивного setimeout обращаться к mongoDB (функция updateAdded), однако внутри settimeout получаю ошибку UnhandledPromiseRejectionWarning:...
Работаю с vue и apiПолучил я массив объектов