#javascript #javascript-objects
#javascript #javascript-объекты
Вопрос:
Я создал WebPage
функцию, которая должна действовать как класс.
У меня есть карта url
ключей и WebPage
значений объектов, и я хочу вызвать метод для каждого объекта. Вызываемый метод startMonitoring
должен устанавливать interval
значение переменной, ограниченной для каждого объекта.
Однако интервал устанавливается только для последнего объекта, и каждый другой объект получит тот же результат при последующей печати.
Вот мой код:
export const startMonitoring = (websitesMap) => {
websitesMap.forEach((website) => {
website.startMonitoring();
});
};
export function WebPage(url, checkTime) {
// other variables
this.scheduledTask;
...
WebPage.prototype.startMonitoring = () => {
this.scheduledTask = setInterval(async () => {
// asynchronous work
}, checkTime * 1000);
};
}
Комментарии:
1.
=>
функции не задаютthis
способfunction
, которым работают функции.2. Каждый раз, когда вы создаете новый экземпляр
WebPage
, вы также переназначаетеWebPage.prototype.startMonitoring
функцию. Я сомневаюсь, что это то, чего вы хотите. Почему вы не используете обычный класс?
Ответ №1:
Это происходит потому, что вы устанавливаете прототип каждый раз, когда создаете новый объект. Таким образом, все экземпляры будут обращаться к последнему, который вы определяете.
И теперь вам придется использовать обычные функции, чтобы иметь доступ к правильным this
.
export const startMonitoring = (websitesMap) => {
websitesMap.forEach((website) => {
website.startMonitoring();
});
};
export function WebPage(url, checkTime) {
// other variables
this.scheduledTask;
this.checkTime = checkTime;
...
}
WebPage.prototype.startMonitoring = function() {
this.scheduledTask = setInterval(async function() {
// asynchronous work
}, this.checkTime * 1000);
};
Ответ №2:
Как сказал Pointy, используя прототип, это сработало бы:
const startMonitoring = (websitesMap) => {
websitesMap.forEach((website) => {
website.startMonitoring();
});
};
function WebPage(url, checkTime) {
// other variables
this.scheduledTask;
this.url = url;
WebPage.prototype.startMonitoring = function() {
this.scheduledTask = setInterval(async () => {
console.log('hello', this.url);
}, checkTime * 1000);
};
}
const websites = [new WebPage('#', 1), new WebPage('#test', 1)]
startMonitoring(websites);
Кроме того, изменение функции прототипа также должно работать:
const startMonitoring = (websitesMap) => {
websitesMap.forEach((website) => {
website.startMonitoring();
});
};
function WebPage(url, checkTime) {
// other variables
this.scheduledTask;
this.url = url;
this.startMonitoring = () => {
this.scheduledTask = setInterval(async () => {
console.log('hello', this.url);
}, checkTime * 1000);
};
}
const websites = [new WebPage('#', 1), new WebPage('#test', 1)]
startMonitoring(websites);
Комментарии:
1. Имейте в виду, что когда вы создаете методы в «классе», подобном этому, у вас будут повторяющиеся экземпляры метода в памяти, тогда как если бы вы использовали методологию прототипа, у вас был бы только один. Пример: jsfiddle.net/Lbqyu096
2. А, понятно. Спасибо.
3. Строка прототипа действительно должна быть вне функции, иначе она будет повторно запускаться для каждого вызова.
4. Хм, тогда мы теряем доступ к переменным экземпляра. Возможно, это должна быть не прототипированная функция?
5. Чтобы иметь доступ к
this
, это должна быть функция-прототип, а не функция со стрелкой