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

说明

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

为什么需要 this

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

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

JavaScript 中的 this 是什么

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

在这里插入图片描述
执行上下文主要分为三种,那么 this 也只有这三种

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

全局执行上下文中的 this

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

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

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

在这里插入图片描述

函数执行上下文中的 this

例子:

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

在这里插入图片描述
打印出来发现还是指向 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)

在这里插入图片描述

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

例子:this 指向了 myObj

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

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

在这里插入图片描述

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

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

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

在这里插入图片描述

在全局环境中调用一个函数,函数内部的 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 tempObj

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

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

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

例子:

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

在这里插入图片描述

解决方法一:声明一个变量用来保存 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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凯小默

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值