javascript中setTimeout()函数
大家都知道javascript中的setTimeput()函数的作用,一般会用他来处理一些连续的事情,们先看一个例子:
<script>
function init()
{
setTimeout("init2()",0);
alert("1");
}
function init2()
{
alert("2");
}
</script>
</head>
<body onload="init()">
</body>
也许很多人认为结果是:2 1, 而恰恰结果是:1 2 。这是为什么呢?明明延迟时间设置的是0,应该是立刻先执行init2()啊?我们可以这样认为,setTimeout()函数会自己重新申请一个堆栈空间,而不属于当前函数init()的堆栈空间,所以init()先入栈,alert("1")第2个入栈,当init()函数执行完后,setTimeout()才执行。
当然这里没有涉及到参数传递,再看这个例子:
<script>
var rgbcolor=new Array(3);
var whichtr=0;
function changeColor(wh)
{
whichtr=wh;
for(var i=0;i<3;i++)
{rgbcolor[i]=Math.ceil(Math.random()*255);}
trID[whichtr].style.backgroundColor="rgb("+rgbcolor[0]+","+rgbcolor[1]+","+rgbcolor[2]+")";
setTimeout("changeColor("+whichtr+")",1000);
}
</script>
</head> <body>
<table border="1" height="400" width="500" align="center" cellspacing="0">
<tr onmousedown="changeColor(0)" id="trID"><td>0</td></tr>
<tr onmousedown="changeColor(1)" id="trID"><td>1</td></tr>
<tr onmousedown="changeColor(2)" id="trID"><td>2</td></tr>
</table>
</body>
当我们在表格里分别单击3个行的后,3个行的背景颜色会分别一直变颜色.这里我们就会要问:当我点击第一行后,whichtr=wh=0;当我们点击第2行后,whichtr=wh=1;此时whichter全局变量已经发生变化了,但此时第一行的颜色还在变化,点击第3行后,前面两行的颜色也一直变化,这是为什么呢?全局变量只有一个whichtr,可是他明明在我们单击后就改变了,但是3行的颜色一直变化,我们所期待的应该是每次点击后只有一行的颜色在改变。
为了看的更清楚的知道全局变量whichtr在程序运行的时变化,我们加入一句代码:document.body.innerHTML+=whichtr;
脚本代码变为:
var rgbcolor=new Array(3);
var whichtr=0;
function changeColor(wh)
{
whichtr=wh;
for(var i=0;i<3;i++)
{rgbcolor[i]=Math.ceil(Math.random()*255);}
trID[whichtr].style.backgroundColor="rgb("+rgbcolor[0]+","+rgbcolor[1]+","+rgbcolor[2]+")";
document.body.innerHTML+=whichtr;
setTimeout("changeColor("+whichtr+")",1000);
}
</script>
此时,我在分别单击表格的三行,结果是:三上的颜色都在改边,whichtr的值是:012012012012...
这时,我们可以知道,全局变量发生了变化,而且一直在变化。
为什么?关键问题是这句代码:setTimeout("changeColor("+whichtr+")",1000);
我们可以这样来分析:
当单击第1行后,whichtr的值是0,当程序执行到setTimeout("changeColor(”+whichtr+")",1000)时,就会把0当作1000MS后执行changeColor()函数的参数.前面我们已经知道,setTimeout函数在内存中会重新申请一个堆栈来保存要运行的函数,所以,此时的whichtr=1已经被保存到另外一个内存单元中了,但这不是本来的whichtr,只能说是一个whichtr的拷贝,当1000MS时间周期到的时候,就会把whichtr==1这个拷贝当做参数传递给changeColor(),执行到whichtr=wh;时,才真正改边了whichtr这个全局变量的值.
程序中每一个onmousedown事件就会产生一个堆栈空间,每一个堆栈空间内都会有一个changeColor()函数,但是全局变量whichtr是共有的,每个堆栈内独立的运行,但这并不是多线程,javascript是单线程的,这只能算一个模拟多线程吧。
总结:
setTimeout()函数在传递参数的时候,是将一个参数的拷贝保存在setTimeout()所在的新的堆栈中,时间周期到的时候,将这个拷贝传递给调用函数。