[英]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
函數。 字符串稱為eval
而eval
類似於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.