执行上下文
js引擎内部有一个执行上下文栈(Excution Context Stack,简称ECS),它是用于执行代码的调用栈。 全局代码块最先执行
- 全局代码块为了执行会创建一个Global Execution Context(GEC);
- GEC被放到ECS中执行,分为两部分
- 第一部分:代码执行前,解析器parser转成AST的过程中,会将全局变量、函数等加入到GlobalObject中,但是并不会赋值,这个过程也叫做变量提升
- 第二部分:在代码执行时会对变量赋值,或者是执行其它函数。
对第一部分进行总结:
- 创建执行上下文,压入执行上下文栈
- 解析器对代码进行解析,对变量进行提升(函数提升先于变量提升),函数会开辟新的堆空间(为了函数可以在定义前调用)
- 执行上下文关联VO(全局代码的VO是GO)、this、作用域链。
var num1=10
var num2=100
function fn(){
var message='hello'
console.log('fn被调用');
}
var num3=200
第二部分总结:
- 变量赋值从上往下
- 执行代码时不会再对函数进行赋值,因为在执行前的解析代码的过程中就已经创建了一个函数对象了
- 遇到函数调用,创建一个函数执行上下文压入执行上下文栈
函数执行上下文
当全局代码执行到函数调用时,会将一个函数上下文压入执行上下文栈,同时开辟新的堆空间创建一个函数的vo对象:Activation Object(AO),对象保存着函数里进行变量提升的属性和方法,接着将AO与执行上下文关联,开始执行代码,代码执行完毕后会将次函数上下文弹出执行上下文栈。
一段代码的执行过程:
arguments是一个对象,保存函数传进去的参数的值。
bar()函数执行完毕后会将相应的上下文执行栈出栈,继续执行栈顶的代码,执行完又出栈,执行全局代码。
作用域的定义
JavaScript中作用域一般指的是变量和函数的可访问性和可见性范围,或者说是某个变量或函数生效的区域。在JavaScript中,作用域主要分为两种:全局作用域和局部作用域,es6中又定义了块级作用域。
- 全局作用域:全局作用域是指在全局范围内声明的变量和函数,它们可以在代码的任何位置被访问。在JavaScript中,全局作用域通常是指在全局作用域下声明的变量和函数,它们可以被整个程序所访问。
- 局部作用域:局部作用域是指声明在函数内部的变量和函数,在函数执行时只能在函数内部被访问。在JavaScript中,每当调用一个函数时,都会创建一个新的局部作用域。这个局部作用域只在函数执行期间存在,函数执行结束后,局部作用域就会被销毁,里面的变量和函数也会消失。
- 块级作用域: 在JavaScript中,作用域是通过作用域链来实现的。当一个变量或函数在某一个作用域中被访问时,JavaScript引擎会先从当前作用域中查找该变量或函数,如果找不到就会沿着作用域链向上层作用域查找,直到找到为止。如果到全局作用域都没找到,那么该变量或函数就会被认为是未定义的(undefined)。
在JavaScript中,作用域是由函数定义时决定的,而不是函数调用时。即使函数在后面的代码里调用,它定义时的作用域也不会改变。这种行为称为词法作用域。
作用域链(scope chain)
- 作用域链是一个对象列表,用于变量标识符的求值 当进入执行上下文时,作用域链就会被创建,并且根据代码类型,添加一系列的对象