簡體   English   中英

從JavaScript計時器調用非全局函數

[英]Invoke a non-global function from a javascript timer

是否有可能以某種方式從計時器調用非全局函數(即類的方法)?

以下示例顯示了我想要實現的目標:

function MyClass() {
  var msg = 'no message';

  // shows an alert after some delay
  this.delayedAlert = function(message) {
    msg = message;

    // global function works:
    //window.setTimeout('globalShow("'+message+'")', 1000);
    // this obviously also works:
    //this.show();

    // this doesn't work: *************
    // I'd like to invoke the show() method of this class after some delay
    window.setTimeout('this.show()', 2000);
  };
  this.show = function() {
    alert(msg);
  };
}

$(document).ready(function() {
  $('p').click(function() {
    var c = new MyClass();
    c.delayedAlert('hello');
  });
});

function globalShow(msg) {
   $('#hello').html(msg);
}

您可以在此處找到運行示例: http : //jsbin.com/aqako5

function MyClass() {
  var msg = 'no message';

  // shows an alert after some delay
  this.delayedAlert = function(message) {
    msg = message;

    window.setTimeout($.proxy(this.show, this), 2000);
  };
  this.show = function() {
    alert(msg);
  };
}

請使用setTimeout函數。 字符串稱為evaleval類似於goto 即猛禽會抓住你。

實際上發生的是在setTimeout函數內部, this值是默認的this值,即window。 你需要在代理法通過,使得this是你想要的this是。

一個替代圖案以正確進行代理this值是:

function MyClass() {
  var msg = 'no message';
  var that = this;

  // shows an alert after some delay
  this.delayedAlert = function(message) {
      msg = message;

      window.setTimeout(function() {
          that.show();
      }, 2000);
    };
    this.show = function() {
        alert(msg);
    };
}

這涉及在單獨的變量中“緩存”正確的this值。 您仍然不能直接傳遞that.show ,因為該函數將在不知道this是什么的情況下被調用。

這會有所幫助。 還可以改善您的課程:如果您的課程未實例化,則可能會引起問題。 如果有人這樣叫您的班怎么辦:

var myClass = MyClass();

MyClass內部的this現在將成為窗口,從而導致各種問題,並將您的屬性添加到全局名稱空間。

要解決此問題,您需要確保在調用類函數時,它是使用new運算符完成的。 您需要在MyClass內部檢查,如果這不是MyClass的新實例,則必須將其強制為新實例。 在下面的代碼中,您可以通過以下兩種方式之一調用此方法,並使它們都以相同的方式起作用:

var myClass = MyClass();
// or
var myClass = new MyClass();

將您的班級更改為此:

function MyClass() {
    // if this isn't an instance, make it so:
    if (!(this instanceof MyClass)) {
        return new MyClass();
    }

    var _this = $(this);    

    var msg = 'no message';
    var show = function() {
        alert(msg);
    };    

    // shows an alert after some delay
    this.delayedAlert = function(message) {
        msg = message;
        window.setTimeout(show, 2000);
    };
}

您也可以通過在每次創建MyClass實例時不創建新的函數定義來改進此代碼。 將您的方法添加到MyClass的原型中:

(function(window) {

    var MyClass = function() {
        // if this isn't an instance, make it so:
        if (!(this instanceof MyClass)) {
            return new MyClass();
        }
    };

    var msg = 'no message';
    var show = function() {
        alert(msg);
    }; 

    MyClass.prototype.delayedAlert = function(message) {
        msg = message;
        window.setTimeout(show, 2000);
    };

    window.MyClass = MyClass;

})(window);

您可以聲明一個匿名函數:

window.setTimeout(function () {
    this.show();
}, 2000);

並且,根據函數的不同,您可以將函數本身傳遞給setTimeout

window.setTimeout(this.show, 2000);

當您將字符串傳遞給setTimeout ,基本上是在告訴瀏覽器等待一定時間,然后eval該字符串。

當瀏覽eval"this.show()" ,它認為this是指全局對象或window

第一條建議使用閉包 ,第二條建議僅傳遞函數本身(不執行 !),因為在JavaScript中, 函數是一類對象 ,可以像其他任何變量一樣對待。

請記住,當您使用第二種解決方案時,您是在將該方法與其上下文分開。 如果您嘗試以下操作...

var msg = 'sadface';

var myObj = {
    msg: 'hello world',
    greet: function () {
        alert(this.msg);
    }
};

window.setTimeout(myObj.greet, 2000);

...然后, this greet不再引用myObj 相反,它將指向window 它會提醒sadface ,不是hello world

祝好運。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM