从底层理解this是什么

作者:dellyoung
出处:
何为this关于this , 我提出了下面几个问题:

  • this存放在哪里?
  • this是如何出现 , 又是如何消失的?
  • this有什么作用?
要完全明白这些 , 咱们要先理解JavaScript执行上下文和调用栈是什么
执行上下文为清晰讲述 this 结合了 《浏览器工作原理与实践》 部分内容
咱们先看下这段代码的函数调用过程:
var a = 2function add(){var b = 10returna+b}add()这段代码很简单 , 先是创建了一个 add 函数 , 接着在代码的最下面又调用了该函数 。
在执行到函数 add() 之前 , 也就是第6行之前 , JavaScript 引擎会为上面这段代码创建全局执行上下文 , 包含了声明的函数和变量 , 你可以参考下图:
从底层理解this是什么文章插图
从图中可以看出 , 代码中全局变量和函数都保存在全局上下文的变量环境中 。
执行上下文准备好之后 , 便开始执行全局代码 , 当执行到 add 这儿时 , JavaScript 判断这是一个函数调用 , 那么将执行以下操作:
  • 首先 , 从全局执行上下文中 , 取出 add 函数代码 。
  • 其次 , 对 add 函数的这段代码进行编译 , 并创建该函数的执行上下文和可执行代码 。
  • 最后 , 执行代码 , 输出结果 。
就这样 , 当执行到 add 函数的时候 , 我们就有了两个执行上下文了——全局执行上下文和 add 函数的执行上下文 。
也就是说在执行 JavaScript 时 , 可能会存在多个执行上下文 , 那么 JavaScript 引擎是如何管理这些执行上下文的呢?
答案是 通过JavaScript调用栈来管理的, 接下来咱们来看下什么是JavaScript调用栈 。
JavaScript调用栈咱们知道 , JavaScript执行过程中 , 内存空间主要分为栈空间和堆空间(代码空间先不用管) 。
什么是 JavaScript 的调用栈:代码执行过程中 , JavaScript 引擎会将执行上下文压入栈空间中 , 通常把这种用来管理执行上下文的栈称为执行上下文栈 , 又称调用栈 。
接下来我们一步步地分析在下面代码的执行过程中 ,JavaScript 调用栈的状态变化情况:
var a = 2function add(b,c){return b+c}function addAll(b,c){var d = 10result = add(b,c)returna+result+d}addAll(3,6)第一步 , 创建全局上下文 , 并将其压入栈底 。
如下图所示:
从底层理解this是什么文章插图
从图中你也可以看出 , 变量 a、函数 add 和 addAll都保存到了全局执行上下文的变量环境对象中 。
全局执行上下文压入到调用栈后 , JavaScript 引擎便开始执行全局代码了 。 首先会执行 a=2 的赋值操作 , 执行该语句会将全局上下文变量环境中 a 的值设置为 2 。
设置后的全局上下文的状态如下图所示:
从底层理解this是什么文章插图
第二步是调用 addAll 函数 。 当调用该函数时 , JavaScript 引擎会编译该函数 , 并为这个函数创建一个执行上下文 , 最后将该函数的执行上下文压入栈中 , 如下图所示:
从底层理解this是什么文章插图
第三步 , 当执行到 add 函数调用语句时 , 同样会为其创建执行上下文 , 并将其压入调用栈 , 如下图所示:
从底层理解this是什么文章插图
当 add 函数返回时 , 该函数的执行上下文就会从栈顶弹出 , 并将 result 的值设置为 add 函数的返回值 , 也就是 9 。 如下图所示:


推荐阅读