之前看了一些关于作用域的文章和书,可是都渐渐淡忘了,这里我在重新复习作用域之前,先去了解一下js引擎编译的大致过程,来帮助我加深对js的理解.
渲染引擎
浏览器的核心是两部分:渲染引擎和javascript解释器(引擎);不同的浏览器有不同的渲染引擎,他的主要作用是生成网页,通常分成四个阶段,因为图片看起来更加直观,所以把内容放在图片里.
javascript虚拟机(引擎)
-
js是解释型语言,有一定的优缺点:
-
早期,浏览器内部对js的处理过程:
-
即时编译
为了提高运行速度,现代浏览器改为采用'即时编译'(just in time compiler,缩写JIT),即字节码只在运行时编译,用到哪行,就编译哪一行,并且把编译结果缓存,通常,一个程序被经常用到的,只是其中一小部分的代码,有了缓存的编译结果,整个程序的运行速度就会显著提升.
有的浏览器索性省略了字节码的翻译步骤,直接编译成机器码,比如CHROME浏览器的v8引擎.
- 字节码不能直接运行,而是运行在一个虚拟机之上,一般也把虚拟机称为'javascript引擎'.因为js运行时未必有字节码,所以js虚拟机并不完全基于字节码,而是部分基于源码,即只要有可能,就通过JIT编译器直接把源码编译成机器码运行,省略字节码步骤,这一点与其他采用虚拟机的语言不尽相同,这样做的目的,是为了尽可能地优化代码,提高性能.
script标签的工作原理
正常的网页加载流程:
为了避免发生阻塞效应,较好的做法是将script标签都放在底部,而不是头部.这样即使遇到脚本失去响应,网页主体的渲染也已经完成了,用户至少可以看到内容,而不是面对一张空白的页面.
如果某些脚本代码非常重要,一定放在页面头部的话,最好将代码嵌入页面,而不是链接外部脚本文件,这样能缩短加载时间
将脚本放在网页尾部加载还有一个好处,在DOM结构生成之前就调用DOM,js会报错,如果脚本都在网页尾部加载,就不存在这个问题,因为这时DOM肯定已经生成了.
defer属性
为了解决脚本文件下载阻塞网页渲染的问题,一个方法是加入defer属性
-
defer属性的作用是,告诉浏览器,等到DOM加载完成后,再执行指定脚本
-
有了defer属性,浏览器下载脚本文件的时候,不会阻塞页面渲染.下载的脚本文件在DOMContentLoaded事件触发前执行(即刚刚读取完