js执行的时候,是怎么去执行的呢?代码的执行顺序是怎么样的?执行的这个过程,都发生了什么事情?
问题
请描述一下js在执行代码的过程是怎么样的?
先了解一下作用域
什么叫做作用域?就是变量影响的范围
js使用的是词法作用域,就是静态作用域,函数的作用域在函数定义的时候就决定了。
执行上下文栈
执行一个函数的时候,就会创建一个执行上下文,并且压入执行上下文栈,当函数执行完毕的时候,就会将函数的执行上下文从栈中弹出。两段代码(冴羽大佬原本例子):
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope();
//执行上下文栈的变化情况
//ECStack.push(<checkscope> functionContext);
//ECStack.push(<f> functionContext);
//ECStack.pop();
//ECStack.pop();
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();
//执行上下文栈的变化情况
//ECStack.push(<checkscope> functionContext);
//ECStack.pop();
//ECStack.push(<f> functionContext);;
//ECStack.pop();
这两段代码运行的结果都是一样的,不一样的是,执行上下文栈的变化不一样\
什么是执行上下文
什么是执行上下文?就是当前javaScript代码被解析和执行时存在的环境
当js执行一段代码时,会做一些准备工作,这个准备工作,就是执行上下文。
全局执行上下文(这是默认的,最基础的执行上下文)
- 不在函数内部的代码都位于全局执行上下文中\
- 创建一个全局对象,其实就是我们的windown对象\
- 将this指针指向这个全局对象
函数执行上下文:每次函数被调用的时候,就会创建一个新的执行上下文
- 每个函数都有自己的执行上下文\
- 一个程序中可以存在任意数量的函数执行上下文\
- 每一个函数执行上下文被创建,它都会按照特定的顺序执行一系列的步骤\
执行上下文的生命周期
创建阶段
当函数被调用,但是未执行内部任何代码之前,会做以下几件事:
- 创建变量对象:首先会初始化函数的参数arguments,提升函数声明和变量声明\
- 创建作用域链:作用域链在变量对象之后创建,它本身包含变量对象。它是用来解析变量\
- 确定this指向
执行阶段
执行变量赋值、代码执行。
回收阶段
执行上下文出栈,等待虚拟机回收
描述js执行的过程
s()
console.log(s);
var s = '我是变量'
function s() {
console.log('函数执行');
}
console.log(s);
s()
//因为一开始,是处在于全局作用域下的,所以,全局执行上下文首先进执行上下文栈
//ECStack.push(windowContext)
//然后变量提升
//var s;
//接着函数提升
//function s() {
//console.log('函数执行');
//}
//执行s()
//ECStack.push(S_Context),创建执行上下文,入执行上下文栈
//执行s函数里面的console.log('函数执行'),输出'函数执行';
//s函数执行完毕,出栈 ECStack.pop()
//执行console.log(s),打印s函数
//执行赋值 s = '我是变量' ,此时s函数被s的赋值覆盖了
//执行console.log(s),打印 '我是变量'
//执行s() //报错,因为s已经不是一个函数