- 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)
- 主线程外,还有一个“任务队列”(task queue)。只要异步任务有了结果,就在“任务队列”中放置一个事件,同时执行相应代码。
- 定时器对“任务队列”的工作方式是,当特定时间过去后将代码插入。
- 指定的时间间隔表示何时将定时器的代码添加到队列中,而不是何时实际执行代码。
1. 重复的定时器
- 当使用setIntervel()时,仅当没有该定时器的任何其他代码实例时,才将定时器代码添加到“任务队列”。
- 有两个问题:- 某些间隔会被跳过
- 多个定时器的代码执行之间的间隔可能会比预期的小 
 理解这幅图关键点在于:605ms处,第一个定时器代码仍在运行,同时队列中已经有了一个定时器代码实例,则605ms处被跳过。在600ms多一点处,直接运行405ms添加的代码
 
- 解决办法: 链式调用setTimeout()1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16setTimeout(function(){ 
 //处理中
 setTimeout(arguments.callee,intervel)
 },intervel)
 //使用例子
 setTimeout(function(){
 var div=document.getElementById("myDiv");
 var left=parseInt(div.style.left)+5;
 div.style.left=left+"px";
 
 if(left<200){
 setTimeout(arguments.callee,50);
 }
 
 },50)
2. Yielding Processes
- JavaScript被严格限制了内存大小和处理器时间 
- 其中一个限制是长时间运行脚本,即代码运行超过特定的时间或者特定语句数量就不让它继续执行。 
- 两个原因: - 过长的、过深嵌套的函数调用
- 进行大量处理的循环
 
- 某个循环占用时间长、不需要同步完成、不需要按顺序完成,则可实行数组分块。 
- 基本思路: 为要处理的项目创建一个队列,然后使用定时器取出下一个要处理的项目进行处理,接着再设置另一个定时器。 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- function chunk(array,process[,context]){ 
 setTimeout(function(){
 var item=array.shift();
 process.call(context,item);
 
 if(array.length>0){
 setTimeout(arguments.callee,100);
 }
 },100);
 }
- 克隆数组方法: - array.concat();
3. 函数节流
- 函数节流:阻止某些操作高频率执行。
- 基本思路:某些代码不可以在没有间断的情况下连续重复执行。1 
 2
 3
 4
 5
 6function throttle(method[,context]){ 
 clearTimeout(method.tId);
 method.tId=setTimeout(function(){
 method.call(context);
 },100);
 }
