js代码的执行流程:编译----> 执行。
一、案例一
例如:
var myname ='极客时间';
function showName() {
console.log('函数showName被执行');
}
showName();
这段代码在执行前会先编译。
编译的过程:
-
创建一个该段代码对应的执行上下文,执行上下文有变量环境、词法环境。
-
从上而下的开始编译。
-
当遇到声明时,比如myname的声明,会将myname添加到变量环境中,值为undefined。
-
当遇到函数showName时,将整个函数放到堆中,showName放入变量环境中,showName的地址指向堆中的地址。
执行过程:
-
执行var myname ='极客时间'时,对变量环境中myname进行赋值。
-
执行到showName时,从变量环境总进行查找,找到showName函数时执行。
二、案例二
var a = 2
function add(b,c){
return b+c
}
function addAll(b,c){
var d = 10,
result = add(b,c)
return a+result+d
}
addAll(3,6)
编译过程:
-
创建一个全局上下文,加入a=undefined,function add(b, c){......},function addAll(b, c){......},全局执行上下文入调用栈。
执行过程:
-
执行到var a =2时,从全局执行上下文的变量环境中查找a,找到后,赋值为2。
-
调用addAll函数时,对addAll函数进行编译,创建addAll的执行上下文,b、c、d、result为undefined,并加入addAll的执行上下文的变量环境中。
-
执行addAll函数,发现调用了add函数。
-
编译add函数,创建add函数的执行上下文,b、c为undefined,并加入到add函数的执行上下文的变量环境中,add函数的执行上下文入栈。
-
执行add函数,执行完,add函数的上下文出栈。
-
继续执行addAll函数,执行完上下文出栈。
-
全局上下文出栈。
例子2的调用栈
调用栈是有大小的,超出大小就会报栈溢出的错误。
三、案例三
es6之前,作用域只有全局作用域、函数作用域,es6新加入了块级作用域。块级作用域中定义的变量不会有变量提升,在外部不能被访问到。
function foo(){
var a = 1
let b = 2
{
let b = 3
var c = 4
let d = 5
console.log(a)
console.log(b)
}
console.log(b)
console.log(c)
console.log(d)
}
foo()
上面代码在编译的过程中,var定义的变量会被放进变量环境中,let、const定义的变量会被放进词法环境中。执行时的查找顺序是先词法环境,后变量环境的查找。
总结:
- 编译阶段会将变量、函数存储到变量环境中。
- 执行阶段会对变量赋值,变量的查找和函数的查找。