一、定时器有哪些?
定时器有两个:setTimeout和setInterval。
二、什么是定时器?

function fn(){console.log("我是定时器执行的");}
setTimeout(fn,1000);//1000毫秒后让fn方法运行一次
setInterval(fn,1000)//每隔1000毫秒让fn方法运行一次

三、定时器是如何工作的?
当定时器方法运行的时候,会把它的fn第一个参数安排到一个时间队列里(就是让这个方法fn开始排队,排多久的时间,则第二个参数决定)

setTimeout是让fn排队一次,等1000毫秒后fn执行一次
setInterval是让fn方法每隔1000毫秒就排队并且执行一次,永远执行下去

四、返回值:
当定时器方法运行的时候,它会返回一个正整数。默认情况下,第一次定时器运行返回的这个数是1(即从1开始,除非浏览器已经运行定时器。),第二次运行返回的就是2了,依次递增。
也就是说定时器的返回值,是一个定时器安排的等待队列(一个排队的序号),好比你去银行办理业务的时候,会去取一个流水号一样,比如说你拿到了8号,则表示你排在了第八个队列中。
定时器的返回值是有有效期的,即它表示一个等待的过程。比如下述代码:

var timer=setTimeout(fn,1000);
当上一行代码执行,setTimeout会让fn在1000毫秒后执行,那这个等待的过程就算是一个队列。  setTimeout还会返回一个整数,如果是第一次运行,则返回的这个整数就是1(现在把它的返回值1赋给了timer这个变量)。
但是这个1表示的这个等待过程(或者叫:队列、定时器队列)只在1000毫秒内是有效的,到了1000毫秒fn就执行了,则这个等待过程的使命就完成了,这个编号也会随之失效。
还有一种情况也会让这个编号失效,就是手动清除这个编号为1的等待队列,代码如:
clearTimeout(timer);//这样到1000毫秒的时候,fn也不会运行了。值得注意的是:这个编号失效了,但是timer这个变量里的值还是1,只是1表示的那个定时器队列失效了,而并非把timer里的值清空。理解这一点很重要,要不然下边的示例你会绕不过弯来。
重要的是理解定时器的返回值的意义,这个返回值是个数字,这个数字代表什么意思
**五、清除定时器的方法:**
就是在排队等待执行这个队列失效的方法
清除定时器的方法有两个,clearTimeout和clearInterval
clearTimeout(1);//使定时器队列号为1的那个队列失效
//或写成
clearTimeout(timer);//使定时器队列号为timer值的那个队列失效
或写成
clearInterval(1);
*/
/* 重要小示例:点击切换启停的电子时钟(setTimeout完成的)*/
var timer=null;//事先定义好一个全局变量,用来保存setTimeout的返回值
/* myClock是计算当前时间,并且将时间显示到网页元素中的方法,这是第一步*/
function myClock(){
	var d=new Date;//创建一个时间戳
	var h=d.getHours();//得到当前的小时
	var m=d.getMinutes();//得到分
	var s=d.getSeconds();//得到秒
	var ms=d.getMilliseconds();//得到毫秒
	var clock=document.getElementById('clock');//得到网页上的id为clock的元素
	clock.innerHTML=h+":"+m+":"+s+":"+ms;//把时分秒毫秒拼成的字符串让clock显示
//我们让定时器每隔1000毫秒执行一次myClock方法,在显示的时候,有可能会出现误差,是因为浏览器是还有其它的运行影响了记时
timer=window.setTimeout(myClock,1000);//如果用setTimeout来驱动这个时钟一直运行,则需要把setTimeout运行在这个myClock方法里面,就类似于一个有时间间隔的递归
console.log(timer);//在控制台里输出定时器变量的变化,来加深对定时器变量的理解
}
/*
如果让这个时钟打开网页就运行,只需在这里直接运行myClock方法就可以了,代码如下:
myClock();
*/
/*
如果想用点击事件来控制时钟的启停,则代码如下:
关键是要理解好timer的运用
*/
/******以下是用setTimeout实现的*******/
clock.onclick=function(){
	/*
	通过判断timer的值是否存在,来知道myClock方法是否运行了(就是时钟是否运行了)。timer是个全局变量,默认值是null。myClock方法如果没有运行,则timer的值会一直为null(null做布尔运算是false),如果myClock方法运行了,代码如下:
	timer=window.setTimeout(myClock,1000);
	则定时器会把一个正整数赋给timer(做布尔运算是true)
	*/
	//下边的代码,通过判断timer是null(false)还是整数(ture),来知道当前时钟是在运行还是在停止。

	if(timer){//如果timer是整数,则是true,则说明时钟在运行,则将时钟停止
	clearTimeout(timer);//清除定时器变量就是停止时钟
	timer=null;//这一步是个关键,一定要理解。定时器变量表示的队列虽然被清除停止了,但timer的值还存在呢!cleraTimeout只能清除timer的值表示的队列号,但它并不能把timer保存的数字也清空了。如果没有这一行代码,虽然时钟是停止了,但下一次点击事件再解决的时候,此处的判断还是true,因为timer里还保存着原来定时器方法返回的数字呢,所以在这里一定要把timer置为null
	console.log(timer);
	}else{//如果timer为null,则是false,则执行else,则启动定时器运行时钟
	timer=window.setTimeout(myClock,1000);//把定时器的返回值赋给timer,要理解timer是什么类型的。
	}
	}
/*******以下是用setInterval实现的********/
clock.onclick=function(){
	//下边的代码,通过判断timer是null(false)还是整数(ture),来知道当前时钟是在运行还是在停止。
	if(timer){//如果timer是整数,则是true,则说明时钟在运行,则将时钟停止
	clearTimeout(timer);//清除定时器变量就是停止时钟
	timer=null;
	}else{//如果timer为null,则是false,则执行else,则启动定时器运行时钟
	timer=setInterval(myClock,1000);//把定时器的返回值赋给timer,要理解timer是什么类型的。
	}
	}
	//1000,再执行一次myclock
	//window.setInterval(myClock,1000);//如果用setInterval来执行,务必写在函数的外边