从底层理解this是什么( 二 )
文章插图
紧接着 addAll 执行最后一个相加操作后并返回 , addAll 的执行上下文也会从栈顶部弹出 , 此时调用栈中就只剩下全局上下文了 。 最终如下图所示:
文章插图
至此 , 整个 JavaScript 流程执行结束了 。
好了 , 现在你应该知道了调用栈是 JavaScript 引擎追踪函数执行的一个机制 , 当一次有多个函数被调用时 , 通过调用栈就能够追踪到哪个函数正在被执行以及各函数之间的调用关系 。
重看this相信根据上文内容大家应该已经明白什么是JavaScript执行上下文和调用栈了
我们再来看this , 其实它也存放在执行上下文中 。
执行上下文包括了:变量环境、词法环境、outer、this 。 如下图所示:
文章插图
从图中可以看出 , this 是和执行上下文绑定的 , 也就是说 每个执行上下文中都有一个 this
执行上下文主要分为三种
- 全局执行上下文
- 函数执行上下文
- eval 执行上下文
- 全局执行上下文中的 this
- 函数中的 this
- eval 中的 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() 的this2.通过对象调用方法设置尝试执行下面的代码
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.根据上面两点得出小结论- 在全局环境中调用一个函数 , 函数内部的 this 指向的是全局变量 window 。
- 通过一个对象来调用其内部的一个方法 , 该方法的执行上下文中的 this 指向对象本身 。
- 谁调用函数 , 函数的this指向谁。 对象调用函数自然不必说 , 全局环境调用其实也可以理解为window来调用 , 所以当然指向了window
推荐阅读
- 资本的价值观:996是福报?底层人物就是用命换钱?
- 数据|新基建时代,高大全的数据管理解决方案是怎样“炼”成的?
- 魅族 17 系列即将升级 Android 11 系统底层
- 官方爆料:魅族Flyme的Android 11底层安排上了?
- 菜鸟学编程,不懂C++ this指针?还不赶快来学一学
- 田间地头万亿级争锋:互联网巨头与垂直玩家共舞 供应链能力考验底层逻辑
- 深入理解Netty编解码、粘包拆包、心跳机制
- 魅族17升级Android 11系统底层倒计时 12·23内测招募
- 社区团购巨头纷纷入场,底层商贩、老百姓或将成为“鱼肉”
- HFL Redis_10_set类型底层存储数据结构