(本文摘录于阮一峰老师所写文章,https://wangdoc.com/javascript/basic/index.html,作个人学习使用。)
1、代码嵌入网页的方法
网页中嵌入 JavaScript 代码,主要有4种方法。
(1)<script>元素直接嵌入代码。
(2)<script>标签加载外部脚本:加载了外部脚本就不可以直接嵌入代码了
(3)事件属性:比如onclick和onmouseover
(4)URL 协议:<a href="javascript:console.log('Hello')">点击</a>
2、浏览器加载 JavaScript 脚本,主要通过<script>元素完成。正常的网页加载流程是这样的。
浏览器一边下载 HTML 网页,一边开始解析。也就是说,不等到下载完,就开始解析。
解析过程中,浏览器发现<script>元素,就暂停解析,把网页渲染的控制权转交给 JavaScript 引擎。
如果<script>元素引用了外部脚本,就下载该脚本再执行,否则就直接执行代码。(因此一般把script放在末尾)
JavaScript 引擎执行完毕,控制权交还渲染引擎,恢复往下解析 HTML 网页。
3、一般来说,如果脚本之间没有依赖关系,就使用async属性,如果脚本之间有依赖关系,就使用defer属性。如果同时使用async和defer属性,后者不起作用,浏览器行为由async属性决定。
3、不同的浏览器有不同的渲染引擎。
Firefox:Gecko 引擎
Safari:WebKit 引擎
Chrome:Blink 引擎
IE: Trident 引擎
Edge: EdgeHTML 引擎
渲染引擎处理网页,通常分成四个阶段。
解析代码:HTML 代码解析为 DOM,CSS 代码解析为 CSSOM(CSS Object Model)。
对象合成:将 DOM 和 CSSOM 合成一棵渲染树(render tree)。
布局:计算出渲染树的布局(layout)。
绘制:将渲染树绘制到屏幕。
以上四步并非严格按顺序执行,往往第一步还没完成,第二步和第三步就已经开始了。所以,会看到这种情况:网页的 HTML 代码还没下载完,但浏览器已经显示出内容了。
4、渲染树转换为网页布局,称为“布局流”(flow);布局显示到页面的这个过程,称为“绘制”(paint)。它们都具有阻塞效应,并且会耗费很多时间和计算资源。
重流和重绘并不一定一起发生,重流必然导致重绘,重绘不一定需要重流。比如改变元素颜色,只会导致重绘,而不会导致重流;改变元素的布局,则会导致重绘和重流。
作为开发者,应该尽量设法降低重绘的次数和成本。比如,尽量不要变动高层的 DOM 元素,而以底层 DOM 元素的变动代替;再比如,重绘table布局和flex布局,开销都会比较大。
5、下面是一些优化技巧。
(1)读取 DOM 或者写入 DOM,尽量写在一起,不要混杂。不要读取一个 DOM 节点,然后立刻写入,接着再读取一个 DOM 节点。
(2)缓存 DOM 信息。
(3)不要一项一项地改变样式,而是使用 CSS class 一次性改变样式。
(4)使用documentFragment操作 DOM
(5)动画使用absolute定位或fixed定位,这样可以减少对其他元素的影响。
(6)只在必要时才显示隐藏元素。
(7)使用window.requestAnimationFrame(),因为它可以把代码推迟到下一次重流时执行,而不是立即要求页面重流。
(8)使用虚拟 DOM(virtual DOM)库。
6、JavaScript引擎:为了提高运行速度,目前的浏览器都将 JavaScript 进行一定程度的编译,生成类似字节码(bytecode)的中间代码,以提高运行速度。
字节码不能直接运行,而是运行在一个虚拟机(Virtual Machine)之上,一般也把虚拟机称为 JavaScript 引擎。并非所有的 JavaScript 虚拟机运行时都有字节码,有的 JavaScript 虚拟机基于源码,即只要有可能,就通过 JIT(just in time)编译器直接把源码编译成机器码运行,省略字节码步骤。这一点与其他采用虚拟机(比如 Java)的语言不尽相同。这样做的目的,是为了尽可能地优化代码、提高性能。
下面是目前最常见的一些 JavaScript 虚拟机:
- Chakra(Microsoft Internet Explorer)
- Nitro/JavaScript Core(Safari)
- Carakan (Opera)
- SpiderMonkey (Firefox)
- V8(Chrome, Chromium)
网友评论