网站为什么把 JS 调用放到网页底部

js在页面中不同位置带来的影响或效果区别

(这里将是讲浏览器资源加载原理和js执行原理的,用通俗易懂的方式说明白需要死掉很多脑细胞,查阅很多很多资料,可能包括已经还给老师的E文,会慢一点点。我争取说得通俗易懂,但发现很难,大家要有心理准备。)
要彻底搞懂,为什么别人建议js放在页面的底部,那么我需要从js的语言机制及其运行环境说起。

1,浏览器不是单线程的,它多线程的,如果有必要它还是多进程的。
很多同学并不理解浏览器不是单线程的,别问我为什么,暂时不打算做代课老师,这里有两篇,自己去理解。
浏览器是怎样工作的(一):基础知识
浏览器是怎样工作的:渲染引擎,HTML解析(连载二)
例如,Webkit或是Gecko引擎,都可能有如下线程:
javascript引擎线程
界面渲染线程
浏览器事件触发线程
Http请求线程

2,js是单线程的

在1万次循环迭代过程中,foo()一直先打印了1万次‘first’,定时时间执行时间为0,它也不去执行里面的mylog函数,而是等待循环结束后,再输出1万次‘second’,看起来像运行了两次迭代,是不是表现很怪异?
为什么?
因为JS运行在浏览器中,是单线程的,每个浏览器页面就是一个JS线程,既然是单线程的,在某个特定的时刻只有特定的代码能够被执行,并阻塞其它的代码。而浏览器是多线程的,它又一个名叫Event driven(事件驱动)的线程,而且浏览器具备Asynchronized(异步)执行事件的特性,会创建事件并放入执行队列中,异步执行。
浏览器定义的异步事件有很多种,例如mouse click(鼠标点击事件), a timer firing(定时器触发事件), 或者an XMLHttpRequest completing(XMLHttpRequest完成回调事件),一旦js代码中有这样的事件代码,浏览器就会将它们放入执行队列,等待当前js代码执行完成之后,再按队列情况逐个执行。
于是,我们就看到了上面的 setTimeout(mylog, 0); 这段代码被执行的怪异表现了,也就是mylog的执行顺序被改变了。
一个有用的知识点: setTimeout(func, 0)的作用
让浏览器渲染当前的变化(很多浏览器UI render和js执行是放在一个线程中,线程阻塞会导致界面无法更新渲染)
重新评估”script is running too long”警告
改变代码块的执行顺序

3,浏览器对资源的加载是线性的,可并行的,但js除外

当我们在浏览器的地址栏里输入一个url地址,访问一个新页面时候,页面展示的快慢就是由一个单线程所控制,这个线程叫做UI线程,UI线程会根据页面里资源(资源是html文件、图片、css等)书写的先后顺序,它会按照资源的类型发起http请求来获取资源,当http请求处理完毕也就意味着资源加载结束。
但是碰到javascript文件则不同,它的加载过程被分为两步,第一步和加载css文件和图片一样,就是执行一个http请求下载外部的js文件,但是javascript完成http操作后并不意味操作完毕,UI线程就会通知javascript引擎线程来执行它,如果javascript代码执行时间过长,那么用户就会明显感觉到页面的延迟。



猜你喜欢

转载自blog.csdn.net/TENCENTSYS/article/details/89016622