图解 | JavaScript的作用域和作用域链

文 / 景朝霞
来源公号 / 朝霞的光影笔记
ID / zhaoxiajingjing
图 / 自己画
❥❥❥❥点个赞,让我知道你来过~❥❥❥❥

前情提要:

  1. 题目 | let和var的区别(一、二)
  2. 图解 | let和var的区别(一、二)
  3. 题目 | 带VAR和不带VAR的区别
  4. 图解 | 带VAR和不带VAR的区别
  5. 总结 | LET和VAR区别(三、四)

0 /

GO/VO/AO

  • ECStack:Execution Context Stack 执行环境栈
  • EC:Execution Context 执行环境(执行上下文)

    • VO:Variable Object 变量对象
    • AO:Activation Object 活动对象
  • Scope:作用域
  • Scope Chain:作用域链
  • GO:global object 全局对象

1 /

图解来啦~

var ary = [1, 2];
function fn(ary) {
    console.log(ary);
    ary[0] = 10;
    ary = [10];
    ary[0] = 0;
    console.log(ary);
}
fn(ary);
console.log(ary);

咱前面说的(↑前情提要蓝色字可穿越)浏览器在执行代码前会先进行变量提升,那下面这张图呢,再来加点料。

图解 | JavaScript的作用域和作用域链_第1张图片

【图一】画了这些东西:

  1. 浏览器在执行代码时,会开辟出一个专门执行代码的栈内存空间:执行栈(ECStack)
  2. 会有一个全局的执行上下文(EC(G)在浏览器中会指向window),把执行上下文压入执行栈里面进行代码执行:进栈。如果执行完以后没有用了呢,会出栈;有的还有用的,暂时不执行它了,会被压入栈底,换别的来执行(以后再告诉你她叫啥~)
  3. 在EC(G)里面有一个全局对象GO,在浏览器里面会把它赋值给window
  4. 有一块地名叫VO的是用来存储全局上下文的变量
  5. 基本数据类型直接存放在栈内存中;引用数据类型则都存在堆内存中,把堆地址赋值给变量名

图解 | JavaScript的作用域和作用域链_第2张图片

【图二】看看多了啥呀~

  1. 函数创建时,初始化了当前函数的作用域,也就是它的户口所在地:FN[scope]:VO(G)。即:[[scope]] =所在上下文EC中的变量对象VO/AO

    • 浏览器的执行栈:ECStack
    • 代码执行的上下文:EC(G) 全局执行上下文,EC(FN)函数执行上下文

      • VO 变量对象——只有全局执行上下文里面才有:存放着全局上下文的变量
      • AO 活动对象——函数执行上下文里面才有,是VO的一个分支:存放着函数执行上下文的变量
    • 作用域:函数创建的地方,它的户口所在地
  2. 每一次一个函数执行都会创建一个全新的函数执行上下文,AO里面存放着当前这个上下文的一些东西

    • 初始化THIS指向
    • 初始化作用域链:scopeChain:<自己执行的创建的变量对象, 户口所在地>
    • arguments 实参集合
    • 形参赋值、变量提升......
  3. 还有很重要的一步:请看下图【图三】

(OS:这里不是俄罗斯套娃呀~~~)执行栈、执行上下文、作用域、作用域链 动手画起来~呀!

图解 | JavaScript的作用域和作用域链_第3张图片

【图三】我不是故意要画这么长的~

当函数执行时,会创建一个全新的执行上下文,它肯定是必须要放在执行栈里面的。

此时,EC(G)全局执行上下文暂时不执行了,会把它往栈底压,把需要执行的EC(FN)函数执行上下文放到栈里面执行。

函数执行:

  1. 创建一个全新的执行上下文,放到执行栈中
  2. 初始化THIS
  3. 初始化作用域链scopeChian:
  4. AO变量对象存储内容:arguments、形参赋值、变量提升....
  5. 代码执行

当EC(FN)中的代码执行完了,它没有被外界占用的东西了,它就可以出栈了。那么,浏览器会择一个良辰吉时(浏览器的垃圾回收机制)把它释放并销毁。EC(G)就会重新调回来继续执行了。

请看【图四】【图五】

图解 | JavaScript的作用域和作用域链_第4张图片

2 /

多画图、自己画

那么,就把之前的题目自己重新画一遍吧~

  1. 题目 | let和var的区别(一、二)
  2. 图解 | let和var的区别(一、二)
  3. 题目 | 带VAR和不带VAR的区别
  4. 图解 | 带VAR和不带VAR的区别
  5. 总结 | LET和VAR区别(三、四)

3 /

背、背、背

Array.prototype上的方法名字背成绕口令的速度脱口而出

  1. toLocaleString、toString
  2. push、pop、shift、unshift
  3. concat、slice、splice
  4. reverse、sort
  5. every、filter、forEach、map、some
  6. indexOf、lastIndexOf
  7. reduce、reduceRight
  8. join
  9. copyWithin、entries、fill、find、findIndex、flat、flatMap、includes、keys、values
绕口令呀
​ 八百标兵奔北坡,
​ 炮兵并排北边跑。
​ 炮兵怕把标兵碰,
​ 标兵怕碰炮兵炮。

来,捋顺一下舌头
​ 八了百了标了兵了奔了北了坡,
​ 炮了兵了并了排了北了边了跑。
​ 炮了兵了怕了把了标了兵了碰,
​ 标了兵了怕了碰了炮了兵了炮。

方法的用法请参考:

  1. 《JavaScript高级程序设计(第3版)》5.2节
  2. 地址:https://developer.mozilla.org...

先背过方法名、再熟知方法的用途。先简易的来,然后再一层层往上加,慢就是快

整理方法可以从4个维度:1. 功能 2. 参数 3. 返回值 4. 原数组:是否变化

△ 文章首发,ID :zhaoxiajingjing

你可能感兴趣的:(javascript,前端)