JavaScript执行上下文和作用域链

执行上下文作用域链

执行上下文(Execution Context):函数执行前进行的准备工作(也称执行上下文环境)

运行 JavaScript 代码的时候,当代码执行进入一个环境时,就会为该环境创建一个执行上下文,它会在运行代码前做一些准备工作,如确定作用域,创建局部变量对象等。

一:JavaScript执行环境
<script>
        //全部变量
        function foo(){
            //局部上下文
            console.log("12");
        }
        foo();//12
        //eval函数:将字符串以js方式来运行
        //eval函数上下文
        eval("let a=1;console.log(a)");  //1
 </script>
1.全局上下文
  • 全局执行上下文
2.局部环境
  • 局部执行上下文
3.eval函数环境
  • eval函数:将字符串以js方式来运行
  • eval函数执行上下文
  • 如果参数是表达式,则 eval() 计算表达式。如果参数是一个或多个 JavaScript 语句,则 eval() 执行这些语句。
二:函数调用栈

在 JavaScript 中,通过栈的存取方式来管理执行上下文,我们可称其为执行栈,或函数调用栈(Call Stack)。

三:执行上下文生命周期
  • 执行上下文创建时会产生作用域链对象
  • 作用域链对象包含变量对象(vo)和scope对象
  • 其中Scope对象不是在执行上下文创建时产生,而是在函数声明时就产生了
  • Scope保存的是声明该函数所在的执行上下文的作用域链对象
1.创建阶段
  • 创建变量
  • 初始化作用域链
  • 确定this指向
  • 确定作用域
2.执行阶段
  • 变量对象赋值
  • 调用函数
  • 顺序执行其他代码
四:执行上下文和作用域的区别

前面有提到,执行全局代码时,会产生一个执行上下文环境,每次调用函数都又会执行上下文环境。当函数调用完成时,这个上下文环境以及其中的数据都会被消除(除了闭包),处于活动状态的执行上下文环境只有一个。

而作用域在函数定义时就已经确定了,不是在函数调用时确定(区别于执行上下文环境,当然 this 也是上下文环境里的成分)

作用域只是一个"地盘",其中没有变量。变量是通过作用域对应的执行上下文环境中的变量对象来实现的。所以作用域是静态观念的,而执行上下文环境是动态上的,两者并不一样。

五:变量对象

在函数的建立阶段,首先会建立 Arguments 对象。然后确定形式参数,检查当前上下文中的函数声明,每找到一个函数声明,就在 variableObject 下面用函数名建立一个属性,属性值就指向该函数在内存中的地址的一个引用。如果上述函数名已经存在于 variableObject(简称VO) 下面,那么对应的属性值会被新的引用给覆盖。最后,是确定当前上下文中的局部变量,如果遇到和函数名同名的变量,则会忽略该变量。

六:作用域链

所谓作用域链,就是内部上下文所有变量对象(包括父变量对象)的列表。此链主要是用于变量查询。

scope:作用域链对象(声明对象的时候就开始产生scope了)

 var a=50;
        function foo1(){
            console.log(`foo1:${a}`);  //undefined
            var a = 100;
        }
        foo1();
        console.log(`全局:${a}`);  //50
        //当函数里面的var a = 100;改为a=100时,会输出(foo1:50,全局:100

在这里插入图片描述

 var food="鸡翅";
        function eat(){
            console.log("吃",food);//吃鸡翅
        }
        (function(){
            var food = "包子";
            eat();   
        }())

谁声明的函数就执行谁的作用域链

 var food = "鸡翅";
        (function () {
            var food = "包子";
            function eat() {
                console.log("吃", food);//吃包子
            }
            eat();
        }())
  var a = 1;
        function b() {
            console.log(a);
            a = 10;  //a与函数名重名,把栈里面的存放一个地址的a改为10(a是一个函数)
            console.log(a);
            return;
            function a() {

            }
        }
        b();
        alert(a);  //1
 var f = true;
           if (f === true) {
               var a = 10;
           }
           function fun() {
               var b = 20;  //var在函数里面无法提升变量到函数外
               c = 30;      //非严格模式下,如果作用域中没有所查询变量,全局作用域就会自动创建一个具有该名称的变量
           }
           fun();
           console.log(a);
           console.log(b);
           console.log(c);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值