掌握 JavaScript 中的“this”
简而言之,“这”是什么
#规则 1. 默认绑定
规则2.隐式绑定
规则3.显式绑定
规则4. 新的绑定
规则5. 词汇绑定
结论
感谢信
在本文中,我们介绍了 JavaScript 中非常重要但又令人困惑的主题——“ this ”关键字。
TL;DR
如果“ this ”让你感到害怕,别担心!我们将学习如何使用五个简单的规则来确定“ this ”关键字的值。
这五条简单规则如下:
- 常规方法—— 默认绑定
- 对象内部的函数——隐式绑定
- 函数借用——显式绑定
- 使用函数创建对象——新绑定
- 箭头函数与常规函数的区别—— 词汇绑定
别担心这些吓人的名字。计算机科学的人喜欢把术语命名得像外星生物一样。其实,它们只是一些普通的概念,任何愿意理解的人都能理解。
this变量对应于函数的调用方式。这些规则帮助我们在各种情况下确定this的值。
一旦你理解了这些规则,你就不会再害怕它们了。
在我们开始之前,请先阅读本文以了解其工作原理。
简而言之,“这”是什么
在 JavaScript 中,每当调用一个函数时,JavaScript 引擎都会创建一个新的执行上下文。该执行上下文会一直存在,直到函数执行完毕。每个执行上下文都包含一个名为“this”的变量。
#规则 1. 默认绑定
当以上面所示的标准方式调用函数时,“ this ”实际上将引用全局对象!
在浏览器中,全局对象意味着Window对象。
需要记住的一个例外是启用严格模式时。通过编写“use-strict”,您可以阻止在全局对象上声明任何内容。
规则2.隐式绑定
如果函数包含在一个对象中,那么该对象将被“this”引用。
对于上述内容,this
关键字将指向personObj
规则3.显式绑定
我们了解了this
指向全局对象的指针,以及在另一种情况下,它指向包含它的对象。如果能够在函数调用时控制这个变量的最终结果,岂不是很棒?
像call、apply和bind这样的词通常会让新开发者感到恐惧。实际上,它们都是可以用来显式设置 this 值的函数。
让我们通过一个例子来理解它。
假设我们有两个对象,personObj
假设readerObj
两个对象都有一个 name 属性。personObj
有一个可以打印 内部值的函数name
,但是 却readerObj
没有任何这样的功能!
这里我们可以使用以下三种方法之一—— call
,apply
或bind
。
这个过程称为功能借用。
我们借用sayName
了readerObj.
现在我们可以打印 name 属性readerObj
sayName
我们从调用方法personObj
,但同时,我们指示 JavaScript 引擎sayName
方法中的“this”变量应该指向readerObj
。
所以当JavaScript引擎执行代码时,函数中的thissayName
变量不是指向personObj
而是指向readerObj
。
这有道理吗?
不仅如此——我们还可以在使用该call
函数时传递一些参数。
我们通过 Namaste 作为论据
我们可以在方法中利用参数sayName
。
当我们执行代码时,我们将获得输出以及传递的参数。
apply 方法的工作方式相同,但它不是以常规参数为参数,而是以数组为参数。
bind 方法也以相同的方式工作——它可以接受常规参数。
但与call和apply不同 ——bind返回一个函数——该函数可以存储在变量中并可以在将来执行。
我们可以看到在函数柯里化中使用 bind —— 这个主题我们将在以后介绍。
规则4. 新的绑定
我们使用new关键字来创建对象的实例或副本。new 关键字的作用是:
- 它创建一个空对象,然后指示关键字this指向该空对象。
return this
然后它在该函数的末尾添加一个语句。
请记住,当使用new关键字创建对象实例时,“ this ”始终指向新创建的实例。
让我们通过一个例子来理解这一点。
当我们运行此代码时,我们应该得到什么?
正如我们所说的——一个空的对象!
幕后发生的事情是
什么?我们要调用这个函数吗?
是的!
瞧,我告诉过你它正在被调用。
让我们来看一下事情的整个经过。
如果我们在函数中放入一些值,它会将其放入新创建的对象中然后返回它!
当我们console.log(newPersonObj)
让我们用动画来完成这个概念。
由于dev.to
仅支持 500 帧的动画,因此我附加了动画的外部链接,
点击此处查看动画
在上面的例子中,我们使用一个函数来创建一个对象。
这种类型的函数称为函数构造函数。
请记住,在newPersonObj
存储副本的中personObj
,“this”变量指向空personObj
现在有意义了吗?
好!现在让我们了解最后一条规则。
规则5. 词汇绑定
随着 ES6 的出现,我们迎来了箭头函数。箭头函数以其极其精简的语法,自然而然地取代了传统的匿名函数。
要显式调用箭头函数,就像常规匿名函数一样,您需要先将其分配给变量:
箭头函数就像常规匿名函数一样,但有一个主要例外——函数内部此对象的行为。
在常规函数中,“ ”的值this
是基于上下文的 - 在链接内调用该函数,“ this
”指向链接的对象;在另一个函数内调用它setInterval()
,则“ this
”指向全局窗口对象。
例如,以下示例尝试调用start()
自定义对象的方法,使其计数器属性每秒增加 1,但由于对“ this
”对象引用计数器的错误假设而失败。
上述代码this.counter
未能正确引用对象的 counter 属性countup
,尽管这个错误可能不太容易发现。人们可能会错误地或粗心地认为“ this
”指向该countup
对象,但实际上它指向的是全局window
对象,因为上下文“ this
”在全局 window 方法中被调用setInterval()
。
结果是指向一个不存在的属性的引用,当我们尝试增加它时,window.counter
它会重复返回。为了在匿名函数中正确引用该对象,我们应该在上下文更改为其他对象之前缓存对正确“ ”对象的引用:NaN
countup
this
箭头函数内的“ this
”对象是词法绑定的,这只是一种奇特的说法,即它的值是静态的,并且由“ this
”关键字的定义位置决定。
与常规函数相比,“ ”是动态的,并且基于上下文调用它,而不管定义this
“ ”时的范围如何。this
让我们以前面那个给我们带来麻烦的例子为例,看看如何通过改用箭头函数来直观地解决问题:
我们仅使用箭头函数就解决了这个问题。
结论
如果你理解了所有规则,那就拍拍自己的肩膀吧——这是你应得的!现在你不再害怕 JavaScript 中最令人困惑的概念——“ this ”关键字了。
在本文中我们了解到:
- 当以上面所示的标准方式调用函数时,“ this ”实际上将引用全局对象!
- 如果函数包含在一个对象中,那么“ this ”将指向该对象。
- call、 apply和bind是 JavaScript 提供给我们的函数,用来改变程序中“ this ”的行为。
- new关键字或运算符用于创建一个空对象,然后指示“ this”指向新创建的对象
- 箭头函数使我们能够在程序中词法绑定“ this
this
”关键字,这意味着它的值是静态的,并且由“ ”关键字定义的位置决定。
感谢信
我想借此最后一次机会向您表示感谢。
谢谢你来看我!如果没有像你这样的人一直关注我,并勇敢地阅读我的帖子,我不可能取得今天的成就。
希望您能关注我未来的博客文章,并持续关注,因为我认为我们这里有一些很棒的内容。也希望在未来的岁月里,我能在您的职业生涯中为您提供帮助!
下次再见。再见!
文章来源:https://dev.to/polymathsomnath/master-this-in-javascript-1bk