Как использовать «setTimeout» для вызова самого объекта
-
12-09-2019 - |
Вопрос
Почему я не могу использовать setTimeout
в объекте JavaScript?
Message = function () {
...
...
this.messageFactory = ...
this.feedbackTag = document.getElementById('feedbackMessages');
this.addInfo = function (message) {
var info = this.messageFactory.createInfo(message); // create a div
this.feedbackTag.appendChild(info);
setTimeout('this.feedbackTag.removeChild(info)', 5000);
// why in here, it complain this.feedbacktag is undefined ??????
};
}
Спасибо за решение Стива, теперь оно будет работать, если код такой, как показано ниже...поскольку «это» раньше фактически указывало на функцию внутри setTimeOut, оно не может найти сообщение.
Message = function () {
...
...
this.messageFactory = ...
this.feedbackTag = document.getElementById('feedbackMessages');
this.addInfo = function (message) {
var info = this.messageFactory.createInfo(message); // create a div
this.feedbackTag.appendChild(info);
var _this = this;
setTimeout(function() { _this.feedbackTag.removeChild(info); }, 5000);
};
}
Но почему это не сработает, если мы сделаем так:
Message = function () {
...
...
this.messageFactory = ...
this.feedbackTag = document.getElementById('feedbackMessages');
// public function
this.addInfo = function (message) {
var info = this.messageFactory.createInfo(message); // create a div
this.feedbackTag.appendChild(info);
delayRemove(info);
};
// private function
function delayRemove(obj) {
var _this = this;
setTimeout(function() { _this.feedbackTag.removeChild(info); }, 5000);
}
}
Решение
Попробуйте заменить эту строку:
setTimeout('this.feedbackTag.removeChild(info)', 5000);
с этими двумя строками:
var _this = this;
setTimeout(function() { _this.feedbackTag.removeChild(info); }, 5000);
Примечание:
Никогда не проходите setTimeout
строка, поскольку это вызывает eval
(который следует использовать только при необходимости).Вместо этого пройдите setTimeout
ссылка на функцию (это может быть анонимная функция).
Наконец, всегда проверяйте, что this
Ключевое слово указывает на то, на что, по вашему мнению, оно указывает (см. http://www.alistapart.com/articles/getoutbindingsituations).
Решение вопроса 2:
Я считаю, что для нормальных функций this
установлен на window
объект — независимо от того, где они объявлены.Таким образом, перемещение кода в отдельную функцию не решит проблему.
Другие советы
Более аккуратный способ — просто пройти этот в качестве аргумента функции, вызываемой по таймауту:
function delayRemove(obj) {
setTimeout(function(_this) {
_this.feedbackTag.removeChild(obj);
}, 5000, this);
}
Тебе действительно стоит пройти объект в качестве аргумента, просто чтобы убедиться, что он находится в области видимости (количество параметров не ограничено):
function delayRemove(obj) {
setTimeout(function(_this, removeObj) {
_this.feedbackTag.removeChild(removeObj);
}, 5000, this, obj);
}
HTML5 и Node.js расширили setTimeout
функция для приема параметров, которые передаются в вашу функцию обратного вызова.Он имеет следующую сигнатуру метода.
setTimeout(callback, delay, [param1, param2, ...])
Как setTimeout
на самом деле это не функция JavaScript ваши результаты могут различаться в разных браузерах.Я не смог найти каких-либо конкретных подробностей о поддержке, однако, как я уже сказал, это предусмотрено в спецификации HTML5.
Чтобы ответить на ваш последний вопрос:«Почему это не сработает, если мы сделаем это»:
Message = function () {
...
...
this.messageFactory = ...
this.feedbackTag = document.getElementById('feedbackMessages');
// public function
this.addInfo = function (message) {
var info = this.messageFactory.createInfo(message); // create a div
this.feedbackTag.appendChild(info);
delayRemove(info);
};
// private function
function delayRemove(obj) {
var _this = this;
setTimeout(function() { _this.feedbackTag.removeChild(info); }, 5000);
}}
Это не работает, потому что вы передаете неопределенную переменную (info
) вместо определенной переменной (obj
).Вот исправленная функция:
function delayRemove(obj) {
var _this = this;
setTimeout(function() { _this.feedbackTag.removeChild(obj); }, 5000);}