一盏茶的功夫带你掌握烦人的 this 指向问题( 二 )

简介: 一盏茶的功夫带你掌握烦人的 this 指向问题( 二 )

前言

相信很多小伙伴们都被this 的指向问题所折磨过,this 它到底指向哪啊? 今天我们就来聊聊如何判断this 指向哪里,一盏茶的功夫让小伙伴们开心一整天!

文中所实例代码都运行在Chrome浏览器的Console控制台中。

在上篇文章中,我们讲了三种this指针的绑定规则,接下来我们讲讲剩余的两种方法,并拓展一下。

this 的绑定规则

  1. new 绑定

在以前讲构造函数的文章里,我们讲了new关键字的作用,感兴趣的小伙伴们可以去我的主页中看看那篇文章。我们知道,自定义构造函数中,通常使用this为实例对象添加属性和方法,如以下例子:

function Car(color) {
    this.name = 'BMW'
    this.height = '1400'
    this.lang = '4900'
    this.weight = 1000
    this.color = color
}
let car1 = new Car('pink')   // 实例对象
let car2 = new Car('green')

那此时构造函数中的this指向谁呢?我们来输出一下:

image.png

很明显,我们的实例对象中出现了各种的属性,所以,构造函数中的this指向new出来的实例对象本身,这个例子中this分别指向car1car2.

5. 显示绑定 --- call, apply, bind

显示绑定是我们通过call,apply,bind,改变this的指向,我们一起来看看例子:

function foo() {
    console.log(this.a);
}
var obj = {
    a: 2
}
foo()

如果这样调用foo(),那么就是this默认绑定,this指向全局,那么输出undefined,那么我们怎么让this指向obj,输出2呢?

1. call

function foo() {
    console.log(this.a);
}
var obj = {
    a: 2
}
foo.call(obj)

call的作用就是强行把foo中的this指向obj,我们来输出以下来看看:

image.png

如果foo(x, y)中有参数传入,那我们使用call时应该怎么样呢?

function foo(n, m) {
    console.log(this.a, n, m);  // 2 100 200
}
var obj = {
    a: 2
}
foo.call(obj, 100, 200)

2. applyapply方法跟call方法差不多,但是传入参数时需要使用数组来装

function foo(n, m) {
    console.log(this.a, n, m);  // 2 100 200
}
var obj = {
    a: 2
}
foo.apply(obj, [100, 200])

我们来输出一下:

image.png

可以看出,applycall 方法都将this的指向改变了

3. bind

bind的执行结果会返回一个函数体,所以我们需要这样写:

function foo(n, m) {
    console.log(this.a);  // 2 100 200
}
var obj = {
    a: 2
}
var bar = foo.bind(obj)
bar()

如果我们想传入参数:

这里我们举个例子,传入的参数为100和200

var bar = foo.bind(obj, 100, 200)
bar()
// 或者
var bar = foo.bind(obj)
bar(100 200)

箭头函数

箭头函数没有this这个概念,写在箭头函数中的this也是它外层函数的this

首先我们来看一个例子:

var obj = {
  name: 'TOM',
  show: function() {
    var bar = function() {
      console.log(this.name);
    }
    bar()
  }
}
obj.show()

这里bar中的this指向哪呢?因为bar()是直接调用,this的默认绑定规则,那么它指向的是全局,这里就输出undefined

image.png

如果我们这里使用的箭头函数的话:

var obj = {
  name: 'TOM',
  show: function() {
    var bar = () => {
      console.log(this.name);
    }
    bar()
  }
}
obj.show()

箭头函数里是没有this的,如果在箭头函数中写了this,那么this就相当于它的外层函数上面,是它外围函数的this。

上述例题中,由于bar是箭头函数,那么bar内的this就相当于在它的外层函数show上, 那么obj.show()就触发了隐式绑定规则this指向obj,this.name输出TOM

总结

this

  • this的绑定规则
  1. 默认绑定 --- 函数在哪个词法作用域里生效,this就指向哪里
  2. 隐式绑定 --- 当函数被一个对象所拥有,再调用时,此时this回指向该对象
  3. 隐式丢失 --- 当函数被多个对象链式调用时,this指向引用函数的对象
  4. 显示绑定 --- call, apply, bind
  5. new 绑定

箭头函数

箭头函数没有this这个概念,写在箭头函数中的this也是它外层函数的this

今天的内容就到这啦,如果你觉得小编写的还不错的话,或者对你有所启发,请给小编一个辛苦的赞吧

相关文章
|
11月前
|
数据库
卸载YashanDB服务端
本文来自YashanDB官网,主要介绍通过`yasboot`命令卸载YashanDB服务端的详细步骤。操作需在服务器安装用户(yashan)的`install`目录下执行,包括:1) 检查并关闭仲裁模式;2) 卸载数据库;3) 卸载`yasom`与`yasagent`组件;4) 清理环境变量及相关配置。若启用了CPU资源管理或守护进程功能,需额外处理开机自启动配置。
|
数据采集 人工智能 文字识别
高能力全透明双语大语言模型MAP-Neo完全开源,开放所有细节!
近年来,大型语言模型 (LLMs) 在各种任务中取得了前所未有的性能提升。然而,由于商业利益,最强大的模型(如 GPT、Gemini 和Claude)只能通过API访问,并未公开训练细节。
|
SQL 关系型数据库 HIVE
hadoop伪分布式安装部署HIVE
应用场景 当我们按照hadoop伪分布式集群搭建博客搭建了hadoop以后,发现这是一个空的hadoop,只有YARN,MapReduce,HDFS,而这些实际上我们一般不会直接使用,而是需要另外部署Hadoop的其他组件,来辅助使用。
2013 0
|
存储 NoSQL 关系型数据库
重构之道:揭秘大规模系统重构的经验与挑战
重构之道:揭秘大规模系统重构的经验与挑战
2014 2
|
存储 程序员 编译器
C语言内存分区(堆,栈,全局/静态存储区,自由存储区,代码区)与可执行程序的三段-(Text段,Date段,Bss段)
C语言内存分区(堆,栈,全局/静态存储区,自由存储区,代码区)与可执行程序的三段-(Text段,Date段,Bss段)
681 0
|
存储 设计模式 算法
有限状态机FSM
关于状态机,以前写过[用Go实现一个状态机](https://mp.weixin.qq.com/s?__biz=MzUzNzAzMTc3MA==&mid=2247484850&idx=1&sn=5ba31ff066ddeeedab27f9ca9f1b9b58&scene=21#wechat_redirect),只是讲述了如何控制状态的流转,理论上不能算作完整的状态机。
|
弹性计算 安全 Linux
阿里云服务器安装宝塔面板和配置安全组开端口
阿里云服务器安装宝塔面板和配置安全组开端口,阿里云服务器网以CentOS操作系统为例,安装宝塔Linux面板,先远程连接到云服务器,然后执行宝塔面板安装命令,系统会自动安装宝塔面板,安装完成后会返回面板地址、账号和密码,然后在安全组开通宝塔面板端口号
1499 0
|
JavaScript API 开发者
为依赖Angular.js的上古项目给VSCode编写$scope定义跳转扩展插件
虽然Angular.js停止更新已经一年了,但依赖它的上古时代的项目并不少。由于都是使用js开发,很难为其提供很好的维护,所以直到今天开发维护也并不愉快。可以说没有开发插件的支持,再成熟老练的框架都发挥困难。
445 0
为依赖Angular.js的上古项目给VSCode编写$scope定义跳转扩展插件
|
JSON 前端开发 JavaScript
[Golang实战] 带你入手gin框架使用,以项目为例
[Golang实战] 带你入手gin框架使用,以项目为例
|
XML 监控 开发工具
反射埋点方案: 全局点击埋点代理OnClickListener SDK 编写(1)
你在开发中是否遇到过这样的场景,当点击同一个dialog或者button的时候,如果暴击多次,该dialog或button的被点击行为会被瞬间执行多次,这时候有小伙伴可能要想了,我可以做一个view时间戳呀,让它延迟生效。
334 0
反射埋点方案: 全局点击埋点代理OnClickListener SDK 编写(1)

热门文章

最新文章