每天对自己多问几个为什么,总是有着想象不到的收获。 一个菜鸟小白的成长之路(copyer)
第一集:理解js代码的执行流程
想想,当拿到一个网站地址,然后在浏览中打开,就会显示一个页面? 为什么呢?这其中的过程是怎么样的呢?
以 http://www.baidu.com
来解释说明。
http://www.baidu.com
这是一个域名- 当在浏览器中打开网站的时候,就会通过
DNS
,把域名解析成一个IP地址
- 然后就会根据
IP地址
找到对应的服务器
,然后服务器就会返回一个index.html
- 这个
index.html
文件就是浏览器所展示的内容。
在上面的过程中,服务器返回一个
index.html
, 那么浏览器是怎么解析的呢?
通过 浏览器的内核
- 解析
index.html
中的代码,遇到link
标签,就会从服务器中下载css的静态资源
- 如果遇到
script
标签, 就会从服务器中下载js的静态资源
浏览器内核
- Gecko: 早期被 Netscape和 Mozilla Firefox浏览器使用
- Trident: 微软开始,被IE4 ~ IE11 浏览器使用,但是Edge浏览器已经转向
Blink
- Webkit: 用于 Safari, Google Chrome(以前)
- Blink: 是Webkit的一个分支, Google开发,用于 Google Chrome, Edge, Opera
事实上,我们经常说的浏览器内核指的是浏览器的排版引擎
排版引擎,也称为浏览器引擎、页面渲染引擎、样版引擎
JavaScript引擎
- 高级编程语法 都是需要转成 最终的机器指令来执行的
- 我们编写的JavaScript无论你交给浏览器或则 Node执行,最后都是需要被CPU执行的
- 但是CPU只认识自己的指令集,实际上是机器语言,才能被CPU执行
- 所以需要 JavaScript引擎帮助我们将JavaScript代码翻译成 CPU指令来执行
所以,现在常用的引擎 就是 V8引擎
v8引擎 解析 JavaScript代码的基本流程
JavaScript代码 -----> 词法分析,生成tokens -----> 生成抽象语法树(AST) -----> Ignition(解释器),会将AST转换成 ByteCode(字节码)
代码的执行过程
var name = 'copyer'
function foo() {
var name = 'james'
console.log(name)
}
var a = 20
var b = 30
var res = a + b
console.log(res)
foo()
执行上下文栈(调用栈)
js引擎内部有一个执行上下文栈(Execution Context Stack, 简称ECS), 它是用于执行代码的调用栈
里面的代码包含两部分的代码:全局代码(全局执行上下文)
和 函数(函数执行上下文)
初始化全局对象
js引擎会在 执行代码之前,会在堆内存中创建一个全局对象:Global Object (GO)
- 该对象 所有的作用域(scope)都可以访问
- 里面会包含Date、Array、String、Number、setTimeout、setInterval 等等
- 其中还有一个window属性指向自己
console.log(window.window.window) // 都是指向这个全局对象
var GlobalObject = {
Date: function(){},
Array: function(){},
Number: function(){},
setTimeout: function(){},
window: GlobalObject
}
并且还在代码没有执行之前,就是把 GlobalObject
方法执行上文栈中,并且还在 解析 JavaScript代码的词法分析过程中,还会把全局变量和函数加入到 BlobalObject
中,
这个过程也称为变量提升(hoisting)
var GlobalObject = {
Date: function(){},
Array: function(){},
Number: function(){},
setTimeout: function(){},
window: GlobalObject,
name: undefined,
foo: 0x123,
a: undefined,
b: undefined,
res: undefined
}
小结:全局对象(GO)放在 执行上下文栈
中, 栈的最底层;代码没有开始执行的时候,就会先解析,把变量和函数放在GO对象,然后在开始执行的代码的时候,就对变量进行赋值。
函数执行
在执行的过程中执行到一个函数时,就会根据函数体创建一个函数执行上下文(Function Execution Context, 简称FEC),并且压入到 执行上下文栈 中
FEC 中包含三部分内容:
- 第一部分:在解析函数成AST树结构时,会创建一个Activation Object(AO),活跃的对象
- AO中包含形参, arguments,函数定义和函数队形,定义的变量
- 第二部分:作用域链: 由VO(在函数中就是AO对象)和父级VO组成,查找时会一层层查找
- 第三部分: this的值
小结:在执行函数的时候,就会函数执行上下文放到 栈执行上下文栈的最顶端,入栈操作,函数执行完之后,就会进行出栈的操作。
目标
- 理解什么是 执行上下文栈
- 理解GO, 还有里面的规则
- 理解函数执行上文栈, 里面的绑定规则