Javascript 为什么赢了';我的计时器不能增加数字吗?
我最近学习了javascript。我在用它做实验。现在,我试着做一个简单的计时器。代码如下:Javascript 为什么赢了';我的计时器不能增加数字吗?,javascript,Javascript,我最近学习了javascript。我在用它做实验。现在,我试着做一个简单的计时器。代码如下: <html> <head> <script type="text/javascript"> function start(obj) { var t = setTimeout("increment(obj)", 1000); } function increment(obj) { obj.inne
<html>
<head>
<script type="text/javascript">
function start(obj)
{
var t = setTimeout("increment(obj)", 1000);
}
function increment(obj)
{
obj.innerHTML = parseInt(obj.innerHTML) + 1;
start(obj);
}
</script>
</head>
<body>
<p onclick="start(this)">0</p>
</body>
</html>
功能启动(obj)
{
var t=设置超时(“增量(obj)”,1000;
}
功能增量(obj)
{
obj.innerHTML=parseInt(obj.innerHTML)+1;
启动(obj);
}
0
的内容应每秒递增1。有人知道这为什么不起作用吗?问题(或者至少是我看到的第一个问题)是,您正在将字符串“increment(obj)”传递给setTimeout()
方法,但是obj
仅在start()
方法中定义。直到超时触发,您传递的字符串才被实际计算,此时没有obj
变量在范围内
有几种不同的方法可以解决这个问题。一种是将闭包传递给setTimeout()
,而不是JavaScript字符串,如:
function start(obj) {
var nextIncrement = function() {
increment(obj);
};
var t = setTimeout(nextIncrement, 1000);
}
另一个(尽管不太可取)选项是将obj
提升到全局范围,如:
function start(obj) {
window.obj = obj;
var t = setTimeout("increment(obj)", 1000);
}
但是,一般来说,应该避免将字符串传递给setTimeout
(还应该避免不必要地将内容放入全局范围)。正如您所看到的,它可能会导致范围解析问题,对于任何非平凡的操作,它也会使代码的可维护性大大降低。如果可能,总是希望传递函数闭包
此外,以下代码行是:
您应该始终为parseInt
提供基数参数,以避免出现诸如011
之类的值错误(该值为9,而不是11,因为由于前导的0
在base-8中求值)。您只需执行以下操作即可避免这些怪癖:
parseInt(obj.innerHTML, 10)
…强制执行base-10解析
无论如何,这里的工作示例:问题(或者至少是我看到的第一个问题)是您正在将字符串“increment(obj)”传递给setTimeout()
方法,但是obj
仅在start()
方法中定义。直到超时触发,您传递的字符串才被实际计算,此时没有obj
变量在范围内
有几种不同的方法可以解决这个问题。一种是将闭包传递给setTimeout()
,而不是JavaScript字符串,如:
function start(obj) {
var nextIncrement = function() {
increment(obj);
};
var t = setTimeout(nextIncrement, 1000);
}
另一个(尽管不太可取)选项是将obj
提升到全局范围,如:
function start(obj) {
window.obj = obj;
var t = setTimeout("increment(obj)", 1000);
}
但是,一般来说,应该避免将字符串传递给setTimeout
(还应该避免不必要地将内容放入全局范围)。正如您所看到的,它可能会导致范围解析问题,对于任何非平凡的操作,它也会使代码的可维护性大大降低。如果可能,总是希望传递函数闭包
此外,以下代码行是:
您应该始终为parseInt
提供基数参数,以避免出现诸如011
之类的值错误(该值为9,而不是11,因为由于前导的0
在base-8中求值)。您只需执行以下操作即可避免这些怪癖:
parseInt(obj.innerHTML, 10)
…强制执行base-10解析
无论如何,这里的工作示例是:,因为传递到
setTimeout
的字符串是在全局范围内计算的,而不是在函数内的范围内,因此不引用obj
对象
决不能将字符串传递给setTimeout
。而是向其传递函数引用:
function start(obj)
{
var t = setTimeout(function() {
increment(obj);
}, 1000);
}
function increment(obj)
{
obj.innerHTML = parseInt(obj.innerHTML) + 1;
start(obj);
}
我们传递给
setTimeout
的函数是一个闭包,这意味着它对定义它的范围内的项有一个持久的引用。因此,一秒钟后,当计时器机制调用它时,它仍然可以访问start
函数的obj
参数,即使start
函数早就返回了。更多信息:因为传递到setTimeout
中的字符串是在全局范围内计算的,而不是函数中的范围,因此不引用obj
对象
决不能将字符串传递给setTimeout
。而是向其传递函数引用:
function start(obj)
{
var t = setTimeout(function() {
increment(obj);
}, 1000);
}
function increment(obj)
{
obj.innerHTML = parseInt(obj.innerHTML) + 1;
start(obj);
}
我们传递给
setTimeout
的函数是一个闭包,这意味着它对定义它的范围内的项有一个持久的引用。因此,一秒钟后,当计时器机制调用它时,它仍然可以访问start
函数的obj
参数,即使start
函数早就返回了。更多信息:问题在于这行代码:
var t = setTimeout("increment(obj)", 1000);
obj
是功能范围内的标识符——它只能在start
功能中访问。将字符串传递给setTimeout
时,将在全局范围内对其进行计算。这意味着obj
变量不可用,因此不增加任何内容
您应该传递一个函数对象,因为这将创建一个闭包,并且可以访问您的变量:
function start(obj)
{
setTimeout(function() {
increment(obj);
}, 1000);
}
请注意,我已经删除了不必要的
var t=
,因为您没有对计时器标识符执行任何操作。问题在于这行代码:
var t = setTimeout("increment(obj)", 1000);
obj
是功能范围内的标识符——它只能在start
功能中访问。将字符串传递给setTimeout
时,将在全局范围内对其进行计算。这意味着obj
变量不可用,因此不增加任何内容
您应该传递一个函数对象,因为这将创建一个闭包,并且可以访问您的变量:
function start(obj)
{
setTimeout(function() {
increment(obj);
}, 1000);
}
请注意,我已经删除了不必要的
var t=
,因为您没有使用计时器标识符执行任何操作。我已经将您的代码复制到jsFidle并添加了一个工作示例。看见
原始版本中的问题是gl中未定义变量obj