0
点赞
收藏
分享

微信扫一扫

浏览器原理 10 # this:从 JavaScript 执行上下文的视角讲清楚 this


说明

浏览器工作原理与实践专栏学习笔记

为什么需要 this

对象内部的方法中使用对象内部的属性是一个非常普遍的需求。但是 JavaScript 的作用域机制并不支持这一点,基于这个需求,JavaScript 又搞出来另外一套 this 机制

作用域链和 this 是两套不同的系统,它们之间基本没太多联系。

JavaScript 中的 this 是什么

执行上下文中的 this:this 是和执行上下文绑定的,每个执行上下文中都有一个 this。

浏览器原理 10 # this:从 JavaScript 执行上下文的视角讲清楚 this_执行上下文


执行上下文主要分为三种,那么 this 也只有这三种

  1. 全局执行上下文----全局执行上下文中的 this
  2. 函数执行上下文----函数中的 this
  3. eval 执行上下文----eval 中的 this

全局执行上下文中的 this

全局执行上下文中的 this 是指向 window 对象的。

这也是 this 和作用域链的唯一交点,作用域链的最底端包含了 window 对象,全局执行上下文中的 this 也是指向 window 对象。

我们可以打开控制台输入 ​​console.log(this)​

浏览器原理 10 # this:从 JavaScript 执行上下文的视角讲清楚 this_javascript_02

函数执行上下文中的 this

例子:

function foo(){
console.log(this)
}
foo()

浏览器原理 10 # this:从 JavaScript 执行上下文的视角讲清楚 this_javascript_03


打印出来发现还是指向 window 对象,说明在默认情况下调用一个函数,其执行上下文中的 this 也是指向 window 对象的。

改变 this 指向

设置函数执行上下文中的 this 值的三种方式

1. 通过函数的 call、bind 和 apply方法设置

以 call 为例:下面的 this 指向 obj 对象

let obj = {
myName : "kaimo",
}
function foo(){
this.myName = "凯小默"
}
foo.call(obj)
console.log(obj)
console.log(myName)

浏览器原理 10 # this:从 JavaScript 执行上下文的视角讲清楚 this_严格模式_04

2. 通过对象调用方法设置

例子:this 指向了 myObj

var myObj = {
name : "凯小默",
showThis: function(){
console.log(this)
}
}
myObj.showThis()

可以认为 JavaScript 引擎在执行 ​​myObject.showThis()​​​ 时,将其转化为了 ​​myObj.showThis.call(myObj)​

浏览器原理 10 # this:从 JavaScript 执行上下文的视角讲清楚 this_执行上下文_05

使用对象来调用其内部的一个方法,该方法的 this 是指向对象本身的。

改造一下代码:this 又指向了 window 对象

var myObj = {
name : "凯小默",
showThis: function(){
this.name = "kaimo"
console.log(this)
}
}
var foo = myObj.showThis
foo()

浏览器原理 10 # this:从 JavaScript 执行上下文的视角讲清楚 this_javascript_06

在全局环境中调用一个函数,函数内部的 this 指向的是全局变量 window。

通过一个对象来调用其内部的一个方法,该方法的执行上下文中的 this 指向对象本身。

3. 通过构造函数中设置

例子:

function CreateObj(){
this.name = "凯小默"
}
var myObj = new CreateObj()

当执行 ​​new CreateObj()​​的时候,JavaScript 引擎做了如下四件事:

  1. 首先创建了一个空对象 tempObj
  2. 调用 CreateObj.call 方法,并将 tempObj 作为 call 方法的参数,这样当 CreateObj 的执行上下文创建时,它的 this 就指向了 tempObj 对象
  3. 执行 CreateObj 函数,此时的 CreateObj 函数执行上下文中的 this 指向了 tempObj 对象
  4. 最后返回 tempObj 对象

大致就是:

var tempObj = {}
CreateObj.call(tempObj)
return

更多 new 的知识点可以查看​​【new 运算符】​​

this 的设计缺陷以及应对方案

1. 嵌套函数中的 this 不会从外层函数中继承

例子:

var myObj = {
name : "凯小默",
showThis: function(){
console.log(this)
function bar(){console.log(this)}
bar()
}
}
myObj.showThis()

浏览器原理 10 # this:从 JavaScript 执行上下文的视角讲清楚 this_执行上下文_07

解决方法一:声明一个变量用来保存 this,其本质就是把 this 体系转换为了作用域的体系

var self = this;
function bar(){
self.name = "kaimo"
}

解决方法二:使用 ES6 中的箭头函数来解决这个问题

因为 ES6 中的箭头函数并不会创建其自身的执行上下文,所以箭头函数中的 this 取决于它的外部函数。

var bar = ()=>{ 
this.name = "kaimo"
console.log(this)
}

2. 普通函数中的 this 默认指向全局对象 window

可以通过设置 JavaScript 的“严格模式”来解决。在严格模式下,默认执行一个函数,其函数的执行上下文中的 this 值是 undefined

注意点

  1. 当函数作为对象的方法调用时,函数中的 this 就是该对象
  2. 当函数被正常调用时,在严格模式下,this 值是 undefined,非严格模式下 this 指向的是全局对象 window
  3. 嵌套函数中的 this 不会继承外层函数的 this 值
  4. 箭头函数没有自己的执行上下文,所以箭头函数的 this 就是它外层函数的 this。


举报

相关推荐

0 条评论