javascript setTimeout() first argument: expression error
function Timer() {
this.initialTime = 0;
this.timeStart = null;
this.getTotalTime = function() {
timeEnd = new Date();
diff = timeEnd.getTime() - this.timeStart.getTime();
return diff+this.initialTime;
};
this.formatTime = function() {
interval = new Date(this.getTotalTime());
return interval.getHours() + ":" + interval.getMinutes() + ":" + interval.getSeconds();
};
this.start = function() {
this.timeStart = new Date();
setTimeout("this.updateTime()", 1000);
};
this.updateTime = function() {
alert(this.formatTime());
setTimeout("this.updateTime()", 1000);
};
}
timer = new 开发者_开发问答Timer();
timer.start();
I am getting an error:
this.updateTime is not a function
Any ideas?
Thanks
Your string is not evaluated in the context of your object, so this
doesn't refer to what you think it does.
You should not be passing a string argument to setTimeout
. Instead, you should pass an anonymous function that calls your method with a saved copy of this
.
For example:
var self = this;
setTimeout(function() { self.updateTime(); }, 1000);
The self
variable is necessary because setTimeout
's callback is also not evaluated in the context of your object.
try
var me = this;
setTimeout(function() { me.updateTime() }, 1000);
is there a more elegant way?
Yes, in ECMAScript Fifth Edition:
setTimeout(this.updateTime.bind(this), 1000);
However, until all browsers support Fifth Edition (which they don't yet by a long measure), you should add your own implementation of Function.bind as fallback. eg.:
// Add ECMA262-5 method binding if not supported natively
//
if (!('bind' in Function.prototype)) {
Function.prototype.bind= function(owner) {
var that= this;
if (arguments.length<=1) {
return function() {
return that.apply(owner, arguments);
};
} else {
var args= Array.prototype.slice.call(arguments, 1);
return function() {
return that.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments)));
};
}
};
}
You might also prefer to use setInterval
to avoid the repeated setTimeout
calls. Finally, you should remember to declare all your variables (timeEnd
, diff
, etc.) as var
, otherwise you're getting accidental globals, which can cause you horrible debugging heartache.
If you supply a string to setTimeout
, this string will be executed literally. The thing is, it will be executed sometime later in the global context, outside your Timer
object, so this
means something completely different.
Just pass the function itself like so:
function Timer() {
var self = this; // make reference to this that won't change with context
this.updateTime = function() {
alert(self.formatTime());
setTimeout(self.updateTime, 1000);
};
}
精彩评论