web-dev-qa-db-ja.com

「setTimeout」を使用してオブジェクト自体を呼び出す方法

JavaScriptオブジェクトで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);

        setTimeout('this.feedbackTag.removeChild(info)', 5000);
        // why in here, it complain this.feedbacktag is undefined ??????

    };
}

Steve`s Solutionのおかげで、コードが以下のようになっている場合は機能します...以前の 'this'は実際には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);
    }
}
24
jojo

この行を置き換えてみてください:

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

次の2行で:

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

注:

setTimeout 文字列を渡さないでください。これによりevalが呼び出されます(必要な場合にのみ使用してください)。代わりに、 setTimeout 関数参照を渡します(これは無名関数でもかまいません)。

最後に、常にthisキーワードがそれが指していると考えているものを指していることを確認してください( http://www.alistapart.com/articles/getoutbindingsituations を参照)。

質問2に対処:

通常の関数では、thiswindowオブジェクトに設定されていると思います。どこで宣言されているかは関係ありません。したがって、コードを別の関数に移動しても問題は解決しません。

84
Steve Harrison

きちんとした方法は、タイムアウトで呼び出される関数の引数としてthisを渡すだけです。

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

objも引数として渡す必要があります。スコープ内にあることを確認するためです(パラメーターの数は無制限です)。

_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の仕様にあると言いました。

9
Luca Spiller

最後の質問に答えるには、「これを行うとうまくいかない理由」:

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