JavaScript 内的 this 指向

在 javascript 语言中, 有一个奇奇怪怪的 "关键字" 叫做 this为什么说它是 奇奇怪怪 呢, 是因为你写出 100 个 this, 可能有 100 个解释, 完全不挨边,但是, 在你的学习过程中, 搞清楚了 this 这个玩意, 那么会对你的开发生涯有很大帮助的,接下来咱们就开始一点一点的认识一下 this
this 初认识
看到 this, 先给他翻译过来 "这个"到底啥意思呢 ?
饭桌上, 你妈和你说, 你多吃点的这个
商店里, 你媳妇和你说, 这个包 这个包 这个包 我都要
宴会上, 你爸和人介绍说, 这个傻小子是我儿子
你看, 每一句话上都有 "这个", 但是每个 "这个" 都是一个意思吗?并不,就像我们 js 内的 this 一样, 每一个 this 的意思都不一样,但是我们会发现,在说话的过程中, "这个" 是和我们说话的手势有关系在 js 内一个道理,this 的意思是和代码的 "手势" 有关系例子 :
当你媳妇手指着一个 LV 包的时候, 说的 "这个" 指代的就是 LV包
当你妈指着鱼香肉丝的时候说 "这个" 指代的就是 鱼香肉丝
所以在 javascript 内的 this 是要看 "说这句话的代码手指向哪里了"
看看下面一段代码
当你点击 box 这个元素的时候, 会触发后面的函数,然后函数一执行, 就会在控制台打印一下 this,这里的 this 就是 box 这个元素,这就是一个非常简单的 this 指向的例子了
接下来我们就开始详细学习一下 this
给你个概念 , this , 是一个指针形变量, 它动态的指向当前函数的运行环境,"什么鬼东西, 我听不懂啊",给一个私人的解释 : "根据 this 所在的函数是如何被调用的来决定 this 是什么"
举个例子来看一下
因为 this 是在 fn 函数内, 所以 fn 函数的调用方式就决定了这个 this 是什么
因为 this 是在 b 函数内, 所以 b 函数的调用方式决定了 this 是什么, 和 a 函数没关系,就是这个意思,最后, 根据这些年的经验总结给出一个私人的概念, 要牢记
函数的 this
和函数定义在哪没关系
和函数怎么定义没关系
只看这个函数的调用方式
箭头函数除外
对象调用对象调用, 就是利用一个对象作为宿主来调用函数最简单的方式就是把函数写在一个对象内, 利用对象来调用
这时候, 我们调用了和这个对象内的 fn 函数
调用方式就是利用对象调用的函数, 所以在这个函数内的 this 就是 obj 这个对象,换句话说, 只要在这个函数内, 只要出现 this 就是这个对象
全局调用
顾名思义, 全局调用就是直接调用一个全局函数
此时这个函数内的 this 就是 window,可能有的小伙伴觉得疯了,但是我们仔细思考一下, 你会发现,其实 fn 因为是在全局上的, 那么其实调用的完整写法可以写成 window.fn(),此时就回到了之前对象调用那条路上, 这样就通顺了
奇怪的调用
这个时候, 有的小伙伴可能会想到一个问题, 如果这个函数不放在全局呢 ?
此时的 this 应该是什么呢 ?
按照之前的思路思考,○ obj.fn() 确实调用了函数, 但是 this 不是在 obj.fn 函数内, 是在 fun 函数内,○ fun() 确实也调用了函数, 但是我没有办法写成 window.fun(),○ 那么 this 到底是不是 window 呢, 还是应该是 obj 内
答案确实是 window, 这又是为什么呢 ?
捋一下思路
说到这里, 我们会发现,this 真的是好奇怪哦 o( ̄︶ ̄)o 搞不定了,要是按照这个方式, 我来回来去的得记多少种, 谁会记得下来呢
接下来(划重点)
我用写代码三十年的经验给你总结出来了一些内容, 希望你能牢记
this 的个人经验
首先, this 在各种不同的情况下会不一样,那么从现在开始我把我总结的内容毫无保留的传授给你
经验一 :
在 js 的非严格模式下适用
在非箭头函数中适用
不管函数定义在哪, 不管函数怎么定义, 只看函数的调用方式
只要我想知道 this 是谁
就看这个 this 是写在哪个函数里面
这个函数是怎么被调用的
观察 this 在哪个函数内
一定要注意 : 你想知道的 this 在哪个函数内, 就去观察哪个函数的调用方式就好了一些常见的函数调用方式
普通调用
调用方式 : 函数名()
this 是 window
只要你书写 "函数名()" 调用了一个函数, 那么这个函数内的 this 就是 window
2,对象调用
调用方式:
对象.函数名()
对象'函数名'
this 就是这个对象, 对象叫啥, 函数内的 this 就叫啥
3,定时器调用
调用方式
setTimeout(function () {}, 1000)
setInterval(function () {}, 1000)
this 就是 window
一个函数不管是怎么定义的, 只要被当做定时器处理函数使用, this 就是 widnow
4,事件处理函数
调用方式
事件源.on事件类型 = 事件处理函数
事件源.addEventListener(事件类型, 事件处理函数)
this 就是 事件源
只要是作为事件处理函数使用, 那么该函数内的 this 就是 事件源奥,对了,事件就是:在事件中,当前操作的那个元素就是事件源
5,构造函数调用
调用方式
new 函数名()
this 就是该构造函数的当前实例
只要和 new 关键字调用了, this 就是实例对象
记清楚原则 :
不管函数在哪定义,不管函数怎么定义,只看函数的调用方式
经验二 :
在严格模式下适用,其实只有一个,全局函数没有 this, 是 undefined,其他的照搬经验一就可以了
非严格模式
2.严格模式
记清楚原则 :
严格模式下,全局函数没有 this,是个 undefiend
经验三 :
专门来说一下箭头函数,其实也只有一条
推翻之前的所有内容,箭头函数内没有自己的 this,箭头函数内的 this 就是外部作用域的 this
换句话说, 当你需要判断箭头函数内的 this 的时候,和函数怎么调用没有关系了,要看函数定义在什么位置
记清楚原则 :
只要是箭头函数,不管函数怎么调用,就看这个函数定义在了哪里
最后
好了,按照以上三个经验, 记清楚原则,那么在看到 this 就不慌了