JavaScript基础(1)— 执行上下文/作用域链/闭包

  1. 执行上下文概念
    当前JavaScript代码被解析执行时所在的环境。(代码运行的地方)

  2. 执行上下文的类型

  • 全局执行上下文:全局对象(浏览器中的window),只有一个,this指向全局对象;
  • 函数执行上下文:调用函数时都会创建一个函数上下文,可以有无数个;
  • Eval函数执行上下文:执行eval函数中的代码会有自己的执行上下文。
    *** 拓展:Eval函数:eval(string); 计算某个字符串,并执行其中的JavaScript代码。
  1. 执行栈 :用于存储所有的执行上下文,具有LIFO(后进先出)的结构。
---------------------------------------
let a = 'Hello World!';               |
function first() {                    |
--------------------------------      |
    console.log('1');			|     |
    second();                   |  //执行上下文1
    console.log('3');           |     |     
--------------------------------      |      
}                                     |    //全局执行上下文                               
function second() {                   |    
------------------------              |
    console.log('2');   |  //执行上下文2 
------------------------              |
}                                     |                                    
first();                              | 
console.log('4');                     |
---------------------------------------
输出: 1
	  2
	  3
	  4

(1)当浏览器首次载入你的脚本,它将默认进入全局执行上下文,压栈;
(2)首先执行 first();,从而调用函数 first,压栈,创建执行上下文1,输出执行上文1中打印语句中的“1”;
(3)然后执行second();,调用函数second,压栈,创建执行上下文2,输出“2”;
(4)其次继续执行 执行上文1中的打印语句,输出“3”,此时执行上下文1全部执行完毕,出栈;
(5)最后执行全局执行上下文中的打印语句,输出“4”,出栈。

  • 一系列活动的执行上下文从逻辑上形成一个栈。栈底总是全局上下文,栈顶是当前(活动的)执行上下文。当在不同的执行上下文间切换(退出的而进入新的执行上下文)的时候,栈会被修改(通过压栈或者退栈的形式)。

4.执行上下文的创建
在这里插入图片描述

  • 创建阶段:
    this值的决定,即this绑定。
    创建作用域链(Scope Chain),即创建词法环境组件。
    创建变量,函数和参数,即创建变量环境组件。

    this绑定:
    (1)在全局执行上下文中,this的值指向全局对象,(在浏览器中,this引用window对象)
    (2)在函数执行上下文中,this的值取决于该函数是如何被调用的,如果他被一个引用对象调用,那么this会被设置成那个对象,否则this的值被设置为全局对象或者undefined(在严格模式下)。


  • 执行阶段:
    变量赋值。
    函数引用。
    解释/执行其他代码。

5.变量对象(VO):与执行上下文相关的数据作用域,存储了在上下文中定义的变量和函数声明。

  • 全局上下文的变量对象是全局对象

  • 函数上下文的变量对象是活动对象(AO)

    活动对象是在进入函数上下文时刻被创建的,它通过函数的arguments属性初始化,arguments属性值是Argument对象

变量对象包括:
(1)函数所有的形参:a、由名称和对应值组成的一个变量对象的属性被创建。 b、没有实参,属性值设为undefined。
(2)函数声明:a、由名称和对应函数对象组成一个变量对象的属性被创建。 b、 如果变量对象已经存在相同名称的属性,这完全替换这个属性(函数声明提前)。
(3)变量声明:a、由名称和对应值(undefined)组成一个变量对象的属性被创建。b、如果变量名称跟已经声明的形参或函数相同,则变量声明不会干扰已经存在的这类属性。

详戳----建议参考链接:声明提前、变量声明提前、函数声明提前、声明提前的先后顺序 博主写的真心不错!

举例:

function foo(a) {
  var b = 2;
  function c() {}
  var d = function() {};
  b = 3;
}
foo(1);

在进入执行上下文后,这时候的 AO 是:

AO = {
    arguments: {
        0: 1,
        length: 1
    },
    a: 1,
    b: undefined,
    c: reference to function c(){},
    d: undefined
}

在代码执行阶段,会顺序执行代码,根据代码,修改变量对象的值

还是上面的例子,当代码执行完后,这时候的 AO 是:

AO = {
    arguments: {
        0: 1,
        length: 1
    },
    a: 1,
    b: 3,
    c: reference to function c(){},
    d: reference to FunctionExpression "d"
}

总结:

  • 全局上下文的变量对象初始化是全局对象
  • 函数上下文的变量对象初始化只包括 Arguments 对象
  • 在进入执行上下文时会给变量对象添加形参、函数声明、变量声明等初始的属性值
  • 在代码执行阶段,会再次修改变量对象的属性值

参考链接:JavaScript深入之变量对象

6.作用域、词法分析、作用域链

词法分析:在代码执行前,会进行一轮词法分析,分为3个步骤:
(1)分析形参:如果函数有形参,则给当前对象增加形参属性,默认为undefined;
(2)分析变量声明:如果有var声明,若没有该属性则增加以var声明的名称的属性,若已存在相同名称的属性,则不做操作,默认为undefined,注意:变量的复制在执行阶段才进行,词法分析阶段不赋值
(3)分析函数声明:类型function a () {},若当前活动对象没有a命名的属性,则增加该属性,否则直接覆盖原有同名属性。

详戳----建议参考链接: js作用域和词法分析js作用域和词法分析 博主写的真心不错!

作用域链: 在代码执行过程中,查找变量时,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级(词法层面上的父级)执行上下文的变量对象中查到,一直找到全局上下文的变量对象,也就是全局对象,这样由多个执行上下文的变量对象构成的链表就叫做作用域链。
详戳----建议参考链接:JavaScript深入之作用域链 博主写的真心不错!

7.闭包

  • “无论何时声明新函数并将其赋值给变量,都要存储函数定义和闭包。闭包包含在函数创建时作用域中的所有变量,它类似于背包”

详戳----建议参考链接闭包详解 博主写的真心不错!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值