web-dev-qa-db-fra.com

Comment utiliser "Settimeout" pour invoquer l'objet lui-même

Pourquoi ne puis-je pas utiliser setTimeout dans un objet 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 ??????

    };
}

Merci de Steve`s Solution, il fonctionnera maintenant si le code est aussi ci-dessous ... parce que le "Ceci" avant de faire remarquer la fonction au sein de Settimeout, il ne peut pas le message de recherche.

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);

    };
}

Mais pourquoi ne fonctionne pas si nous faisons cela:

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);
    }
}
24
jojo

Essayez de remplacer cette ligne:

setTimeout('this.feedbackTag.removeChild(info)', 5000);

avec ces deux lignes:

var _this = this;
setTimeout(function() { _this.feedbackTag.removeChild(info); }, 5000);

Remarque:

Ne jamais passer setTimeout une chaîne, car cela invoque eval (que vous ne devez utiliser que si nécessaire). Au lieu de cela, passe setTimeout une référence de fonction (cette fonction peut être une fonction anonyme).

Enfin, vérifiez toujours que le mot-clé this désigne ce que vous pensez que cela pointe (voir http://www.alistapart.com/articles/gettbindingsituations ).

Adresse de la question 2:

Je crois que pour les fonctions normales, this est défini sur l'objet window, peu importe où ils sont déclarés. Donc, déplacer le code dans une fonction distincte ne résoudrait pas le problème.

84
Steve Harrison

Une manière de Néater consiste à simplement passer ceci comme un argument à la fonction appelée dans le délai d'attente:

function delayRemove(obj) {
  setTimeout(function(_this) {
      _this.feedbackTag.removeChild(obj);
    }, 5000, this);
}

Vous devriez vraiment passer obj comme un argument également, juste pour m'assurer qu'il est en portée (le nombre de paramètres est illimité):

function delayRemove(obj) {
  setTimeout(function(_this, removeObj) {
      _this.feedbackTag.removeChild(removeObj);
    }, 5000, this, obj);
}

HTML5 et NODE.JS étendue la fonction setTimeout pour accepter les paramètres qui sont transmis à votre fonction de rappel. Il a la signature de méthode suivante.

setTimeout(callback, delay, [param1, param2, ...])

Comme setTimeoutn'est pas une fonctionnalité JavaScript Vos résultats peuvent varier sur des navigateurs. Je n'ai pas trouvé de détails concrets de support, cependant, comme je l'ai dit, c'est dans la spécification HTML5.

9
Luca Spiller

Pour répondre à votre dernière question: "Pourquoi ça ne marche pas si nous faisons cela":

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);
}}

Cela ne fonctionne pas car vous passez une variable non définie (info) au lieu d'une variable définie (obj). Voici la fonction corrigée:

function delayRemove(obj) {
var _this = this;
setTimeout(function() { _this.feedbackTag.removeChild(obj); }, 5000);}
2
ecartsiger