JavaScript 执行过程



JavaScript整个执行过程,分为两个阶段,代码编译阶段和代码执行阶段

  1. 一、编译阶段

编译阶段由编译器执行,将代码翻译成可执行代码,这个阶段确定作用域规则。

变量的预编译只作声明,不作初始化,初始化在执行时

function语句定义的函数,不仅声明了函数名,而且函数体也进行了处理


二、执行阶段

执行阶段由引擎完成,主要任务是执行可执行代码,执行上下文在这个阶段创建。执行上下文也分为创建阶段和执行阶段。

1、执行上下文

执行上下文可以理解为当前代码的执行环境,它会形成一个作用域。

2、三种类型

a、全局执行上下文:浏览器的全局对象是window对象,this指向这个全局对象

b、函数执行上下文:存在无数个,只有在函数被调用的时候才会被创建,每次调用函数都会创建一个新的执行上下文,函数上下文的变量对象初始化只包括 Arguments 对象。

c、Eval函数执行上下文:指运行在eval函数的代码,很少用而且不建议使用。。

创建阶段:

确定this的值,也被成为 This Binding;

This Binding

a、全局执行上下文中,this 指向全局对象,在浏览器中this 指向window对象,在nodejs中指向这个文件的module 对象。

b、函数执行上下文中,this的值取决于函数的调用方式。具体有:默认绑定、隐式绑定、显式绑定、new绑定、箭头函数。

例一:变量提升

foo();  // 报错  
var foo = function () {
    console.log('foo1');
}

foo();  // foo1,foo重新赋值

var foo = function () {
    console.log('foo2');
}

foo(); // foo2,foo重新赋值
复制代码

例二:函数提升

foo();  // foo2
function foo() {
    console.log('foo1');
}

foo();  // foo2

function foo() {
    console.log('foo2');
}

foo(); // foo2
复制代码

例三:声明优先级,函数 > 变量

foo();  // foo2
var foo = function() {
    console.log('foo1');
}

foo();  // foo1,foo重新赋值

function foo() {
    console.log('foo2');
}

foo(); // foo1
复制代码

需要注意的是同一作用域下存在多个同名函数声明,后面的会替换前面的函数声明。


三、执行上下文栈

因为JS引擎创建了很多的执行上下文,所以JS引擎创建了执行上下文(Execution context stack,ECS)来管理执行上下文。

当 JavaScript 初始化的时候会向执行上下文栈压入一个全局执行上下文,我们用 globalContext 表示它,并且只有当整个应用程序结束的时候,执行栈才会被清空,所以程序结束之前, 执行栈最底部永远有个 globalContext。

ECStack = [        // 使用数组模拟栈
    globalContext
];复制代码

当执行一个函数的时候,就会创建一个执行上下文,并且压入执行上下文栈,当函数执行完毕的时候,就会将函数的执行上下文从栈中弹出。

var scope = "global scope";
function checkscope(){
    var scope = "local scope1";
    function f(){
        console.log(scope);
    }
    return f(); //执行
}
checkscope(); 


var scope = "global scope";
function checkscope(){
    var scope = "local scope22";
    function f(){
        console.log(scope);
    }
    return f; //返回function
}
checkscope()();复制代码

第一段代码:

ECStack.push(<checkscope> functionContext);//执行checkscope
ECStack.push(<f> functionContext);//执行f
ECStack.pop();//弹出f
ECStack.pop();//弹窗checkscope复制代码

第二段代码:

ECStack.push(<checkscope> functionContext);//执行checkscope
ECStack.pop();//返回function
ECStack.push(<f> functionContext);//执行f
ECStack.pop();//返回f复制代码





转载于:https://juejin.im/post/5c04c364e51d4539055a6011

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值