了解JavaScript单线程的概念,对于JavaScript学习和掌握它的一些设计机制,比如回调,定时器,是非常重要的。对后续学习NodeJS也很有帮助。通过先演示后总结的形式,更容易理解JavaScript的单线程。1vara=1;//全局变量a2functiontest(){3vara=2;//测试中变量a4setTimeout(function(){5alert(a);//测试中输出变量a6a=3;//测试中修改变量a7},3000);8a=4;//修改变量a9setTimeout(function(){10alert(a);//测试时输出变量a11a=5;//修改变量a12},1000);13alert(a);//在测试中输出变量a14}15test();//执行测试函数16alert(a);//输出全局变量a//运行结果:4145/*结果分析:先输出test()运行结果4,然后下一行代码输出1,然后1000ms后在test()中输出变量a=4,***3000ms后在test()中输出变量a=5*//*操作机制:1.JavaScript是单线程的,从上到下顺序执行2.setTimeout异步方法存放在任务队列中。JS主线程执行完毕后,任务队列中的任务会在JS主线程中取走执行!->先执行15行,再执行16行->执行15行,调用test()方法->调用test()方法,先创建一个变量a,然后把第一个setTimeout放在setTimeout对应的线程中执行(starttimertimer),第8行,修改test中的变量a为4,然后将第二个setTimeout添加到setTimeout对应的线程队列中执行,执行第13行,输出test中的变量a,此时为4;然后执行第16行,输出全局变量a,此时为1。->1000ms后,将setTimeout的第二个回调函数添加到JS任务队列中,将3000ms后的setTimeout第一个回调函数添加到JS任务队列中。->JS主线程执行完成后,会执行任务队列的事件。第二个setTimeout会先进入任务队列,所以会先执行。执行第10行,输出test中的变量a,值为4,然后di11行将test中的变量a改为5;2000ms后,第一个setTimeout进入任务队列。此时JS主线程栈为空,所以加入JS主线程执行。第5行,输出test中的变量a此时变量的值为5,第6行修改test变量a为3。*/由此扩展出如下代码:vara=1;vardate=+newDate();//提示:通过“+”转为整数functiontest(){vara=2;setTimeout(function(){console.log(a+'--'+(newDate()-date));a=3;},3000);a=4;setTimeout(function(){console.log(a+'--'+(newDate()-date));a=5;},1000);console.log(a+'--'+(newDate()-date));}while(newDate-date<1000){}test();console.log(a+'--'+(newDate()-date));//执行结果:4-10001-10014-20005-4001结合下面的博客,整理一些重要的概念:http://www.ruanyifeng.com/blog/2014/10/event-loop.htmlhttp://www.cnblogs.com/Mainz/p/3552717.html1.作为一种脚本语言,JavaScript的主要功能是与用户交互和操作DOM。假设JavaScript同时有两个线程,一个线程向某个DOM节点添加内容,另一个线程删除这个节点,那么浏览器应该以哪个线程为基础呢?->所以:JavaScript是单线程的。2、JavaScript任务分为同步任务和异步任务两种。同步任务:在主线程上排队等待执行的任务,只有在上一个任务执行完毕后才会执行下一个任务。异步任务:对于没有进入主线程而是进入“任务队列”的任务,只有“任务队列”通知主线程某个任务队列可以执行。主线程执行完毕后,任务队列会进入主线程执行。->所以:只要主线程是空的,它就会读取“任务队列”,这是JavaScript的运行机制。3.主线程从“任务队列”中读取事件。这个过程是循环的,所以整个事件也叫“事件循环”。HTML5规定setTimeout()的第二个参数的最小值(最短间隔)不得低于4ms,低于4ms会自动递增。在此之前,旧版本的最小浏览时间设置为10ms。另外,对于那些DOM变化(尤其是设计页面的重新渲染部分),通常不会立即执行,而是每16ms执行一次。这是使用requestAnimationFrame()比setTimeout()效果更好。4、需要注意的是,setTimeout只是将事件插入“事件队列”,主线程只有在前面的代码(执行栈)执行完毕后,才会执行它指定的回调函数。如果当前代码耗时很长,可能要等待很长时间,所以没办法保证回调函数会在setTimeout()指定的时间执行。Javascript是单线程的,这意味着所有任务都需要排队。那么所有的任务分为两类:同步任务和异步任务!同步任务:在主线程上执行的任务,只有上一个任务完成后才会执行下一个任务!异步任务:不进入主线程而是进入“任务队列”的任务。js是单线程的,而浏览器是多线程的!浏览器是事件驱动的!JS运行在浏览器中,是单线程的,每个窗口一个JS线程,但是浏览器不是单线程的。可能有多个线程如下:Javascript引擎线程、界面渲染线程、浏览器事件触发线程、Http请求线程。setTimeout可以改,js的执行顺序。比如:我们要输出HelloWorld,world必须在hello之后输出,不管我们代码的顺序如何,都会输出同样的效果。这时候,我们可以使用setTimeout。//代码1vardate=+newDate();console.log('Hello',newDate()-date);setTimeout(function(){console.log('world',newDate()-date);},500);//代码2:vardate=+newDate();setTimeout(function(){console.log('World',newDate()-date);},500);console.log('Hello',newDate()-date);//结果上面两段代码是一样的,结果都是:先输出Hello,500ms后输出World!【实际运行:501ms】浏览器中的定时器也是一个线程!Javscript是单线程的,ajax请求确实是异步的!原因是ajax请求是在浏览器的Http请求线程中执行的,执行后的回调函数会在Javascript线程中执行!总结:Javascript是单线程的,而浏览器是多线程的。浏览器线程包括:JS引擎线程、界面渲染线程、浏览器事件线程、Http请求线程。但是不同的浏览器提供的线程是不一样的。一般JS引擎线程和界面渲染线程是互斥的,两个线程不能同时执行,否则界面渲染线程和JS线程修改同一个DOM样式会产生矛盾!
