从底层理解this是什么( 二 )


从底层理解this是什么文章插图
紧接着 addAll 执行最后一个相加操作后并返回 , addAll 的执行上下文也会从栈顶部弹出 , 此时调用栈中就只剩下全局上下文了 。 最终如下图所示:
从底层理解this是什么文章插图
至此 , 整个 JavaScript 流程执行结束了 。
好了 , 现在你应该知道了调用栈是 JavaScript 引擎追踪函数执行的一个机制 , 当一次有多个函数被调用时 , 通过调用栈就能够追踪到哪个函数正在被执行以及各函数之间的调用关系 。
重看this相信根据上文内容大家应该已经明白什么是JavaScript执行上下文和调用栈了
我们再来看this , 其实它也存放在执行上下文中 。
执行上下文包括了:变量环境、词法环境、outer、this 。 如下图所示:
从底层理解this是什么文章插图
从图中可以看出 , this 是和执行上下文绑定的 , 也就是说 每个执行上下文中都有一个 this
执行上下文主要分为三种

  • 全局执行上下文
  • 函数执行上下文
  • eval 执行上下文
所以对应的 this 也只有这三种
  • 全局执行上下文中的 this
  • 函数中的 this
  • eval 中的 this(先不讲解此情况)
全局执行上下文中的 this在控制台中输入
console.log(this) // windowconsole.log(this === window) // true我们可以看出来:全局执行上下文中的 this 也是指向 window 对象 。
函数执行上下文中的 this执行下面代码:
function foo(){console.log(this) // window}foo()可以看到输出了window , 说明在 默认情况 下调用一个函数 , 其执行上下文中的 this 也是指向 window 对象的 。
可以认为 JavaScript 引擎在执行foo()时 , 将其转化为了:
function foo(){console.log(this) // window}window.foo.call(window)显然大家发现了可以通过call来改变this指向 。
咱们来列举下设置函数执行上下文中的 this 值的方法:
1.通过函数的 call、apply、bind 方法设置用法如下:
let bar = {myName : "dell",}function foo(){this.myName = "dellyoung"}foo.call(bar)console.log(bar) // {myName:"dellyoung"}console.log(myName) // 报错myName未定义执行上面代码 , 会打印出 {myName:"dellyoung"} 和 myName 未定义的报错信息 , 显然执行 foo() 的时候成功的将其this指向指到了bar , 这时候bar就是 foo() 的this
2.通过对象调用方法设置尝试执行下面的代码
var myObj = {name : "dellyoung",showThis: function(){console.log(this)}}myObj.showThis()打印出了 { name: 'dellyoung', showThis: [Function: showThis] } ,显然现在这个this指向了调用它的myObj 。
可以得到结论: 使用对象来调用其内部的一个方法 , 该方法的 this 是指向对象本身的 。
可以认为 JavaScript 引擎在执行myObject.showThis()时 , 将其转化为了:
myObj.showThis.call(myObj)3.根据上面两点得出小结论