目录
1. javaScript脚本嵌入网页的方法
在一个网页中嵌入JavaScript脚本主要有以下方法:
<script/>
元素直接嵌入代码。<script/>
标签加载外部脚本。- 事件属性
- URL协议
1.1 script元素内嵌代码
<script>
元素内部直接写 JavaScript 代码。
<script>
function handleCurrentChange(val) {
this.pageNum = val
....
}
</script>
<script>
标签的type属性,用来指定脚本类型。type
有以下值可选:
text/javascript
:这是默认值。text/ecmascript
application/javascript
application/ecmascript
text/vbscript
1.2 script 元素加载外部脚本
<script>
标签也可以指定加载外部的脚本文件。所加载的脚本必须是纯的 JavaScript 代码,不能有HTML代码和<script>
标签。
<script charset="utf-8" src="example.js"/>
上面例子中,src
属性表示加载的外部脚本URL
,charset
属性表示外部脚本使用的编码。
1.3 事件属性
网页元素的事件属性,可以写入 JavaScript 代码。当指定事件发生时,就会调用这些代码。
<button id="myBtn" onclick="console.log('你点击我了!')">点击</button>
1.4 URL 协议
URL 支持javascript:协议,使用这个 URL 的时候就会执行 JavaScript 代码。
<a href="javascript:console.log('你点击我了!')">点击</a>
<a href="javascript: void new Date().toLocaleTimeString();">点击</a>
2. script 元素
2.1 工作原理
浏览器加载 JavaScript 脚本,主要通过<script>
元素完成。网页加载流程如下:
- 浏览器一边下载 HTML 网页,一边开始解析。
- 解析过程中,浏览器发现
<script>
元素,就暂停解析,把网页渲染的控制权转交给 JavaScript 引擎。 - 如果
<script>
元素引用了外部脚本,就下载该脚本再执行,否则就直接执行代码。 - JavaScript 引擎执行完毕,控制权交还渲染引擎,恢复往下解析 HTML 网页。
加载外部脚本时,浏览器会暂停页面渲染,等待脚本下载并执行完成后,再继续渲染。因为JavaScript 代码可以修改 DOM,所以必须把控制权让给它,否则会导致复杂的线程竞赛的问题。
如果外部脚本加载时间很长,那么浏览器就会一直等待脚本下载完成,网页会长时间失去响应,浏览器就会呈现“假死”状态。
为了避免外部脚本文件加载时间过长,导致网页一直等待。一般情况下将<script>
标签放在页面底部。
2.2 defer属性
为了解决脚本文件下载阻塞网页渲染的问题,可以给<script>
元素加入defer
属性。
<script src="a.js" defer></script>
<script src="b.js" defer></script>
defer
属性的运行流程如下:
- 浏览器开始解析 HTML 网页。
- 解析过程中,发现带有
defer
属性的<script>
元素。 - 浏览器继续往下解析 HTML 网页,同时并行下载
<script>
元素加载的外部脚本。 - 浏览器完成解析 HTML 网页,此时再回过头执行已经下载完成的脚本。
对于内置而不是加载外部脚本的script
标签,以及动态生成的script
标签,defer
属性不起作用。另外,使用defer
加载的外部脚本不应该使用document.write
方法。
2.3 async属性
还可以给<script>
元素加入async
属性,解决脚本文件下载阻塞网页渲染的问题。
<script src="a.js" async></script>
<script src="b.js" async></script>
async
属性的运行流程如下:
- 浏览器开始解析 HTML 网页。
- 解析过程中,发现带有
async
属性的script
标签。 - 浏览器继续往下解析 HTML 网页,同时并行下载
<script>
标签中的外部脚本。 - 脚本下载完成,浏览器暂停解析 HTML 网页,开始执行下载的脚本。
- 脚本执行完毕,浏览器恢复解析 HTML 网页。
一旦采用async
属性,就无法保证脚本的执行顺序。哪个脚本先下载结束,就先执行那个脚本。另外,使用async
属性的脚本文件里面的代码,不应该使用document.write
方法。
defer
属性和async
属性如何进行选择?
一般情况下,如果脚本之间没有依赖关系,就使用async
属性,如果脚本之间有依赖关系,就使用defer
属性。如果同时使用async
和defer
属性,后者不起作用,浏览器行为由async
属性决定。
3. 浏览器的组成
浏览器的核心是两部分:渲染引擎和 JavaScript 解释器(又称 JavaScript 引擎)。
3.1 渲染引擎
渲染引擎的主要作用是,将网页代码渲染为用户视觉可以感知的平面文档。
不同的浏览器有不同的渲染引擎:
- Firefox:Gecko 引擎
- Safari:WebKit 引擎
- Chrome:Blink 引擎
- IE: Trident 引擎
- Edge: EdgeHTML 引擎
渲染引擎处理网页,通常分成四个阶段:
- 解析代码:HTML 代码解析为 DOM,CSS 代码解析为 CSSOM。
- 对象合成:将 DOM 和 CSSOM 合成一棵渲染树。
- 布局:计算出渲染树的布局(layout)。
- 绘制:将渲染树绘制到屏幕。
以上四阶段并非严格按顺序执行。
3.2 重流和重绘
渲染树转换为网页布局,称为“布局流”;布局显示到页面的这个过程,称为“绘制”。它们都具有阻塞效应,并且会耗费很多时间和计算资源。
页面生成以后,脚本操作和样式表操作,都会触发“重流”和“重绘”。重流和重绘并不一定一起发生,重流必然导致重绘,重绘不一定需要重流。
3.3 JavaScript 引擎
JavaScript 引擎的主要作用是:读取网页中的 JavaScript 代码,对其处理后运行。
不同的浏览器有不同的JavaScript 引擎:
- Microsoft Internet Explorer:Chakra
- Safari:Nitro/JavaScript Core
- Opera:Carakan
- Firefox:SpiderMonkey
- Chrome,Chromium:V8
4. 参考链接
本博客是自己学习笔记,
参考文献如下:
JavaScript教程
W3C
如有问题,请及时指出!
欢迎沟通交流,邮箱:jidi_jidi@163.com。