概述
与其他语言相比,JavaScript 以不同的方式处理此关键字。这个关键字的 Javascript 是最常被误解的想法之一,因为它的行为方式和位置不同。让我们尝试根据您如何调用该关键字以及它是在严格模式还是非严格模式下运行来确定此关键字的上下文。
介绍
JavaScript 中的 this 关键字是指对象。this 引用的对象携带当前正在运行的程序。因此,这是指执行当前正在执行的功能的对象。当引用常规函数时,它指的是全局对象。如果被引用的函数是对象中的方法,则这是指对象本身。它的使用或调用方式决定了引用哪个对象。
JavaScript 中最常用的关键字之一是 this 关键字。一开始可能看起来很困难,但一旦你开始使用这个关键词,一切都会清楚。
根据它的使用方式,this 关键字可用于指代各种对象:
- this 指的是 object 方法中的对象。
- 仅此一项就表示全局对象。
- 全局对象由函数中的 this 引用。
- 在函数中,这在严格模式下是未定义的。
- 对于事件,接收该事件的元素称为 this。
- call()、apply() 和 bind() 方法都可以使用它来引用任何对象。
默认使用“this”箭头功能
与常规函数相比,箭头函数的处理方式不同。换句话说,这与箭头函数没有绑定。在常规函数中,调用函数的对象由 this 关键字表示。对于常规函数,此对象可以是窗口、文档、按钮或其他任何对象。
这是基于箭头函数的封闭词法范围。在箭头函数中,使用标准变量查找。如果他们无法在当前范围内识别封闭范围,则继续进入封闭范围。因此,箭头函数不是绑定自己的 this,而是从父作用域继承“this”。此过程称为词法范围。因此,箭头功能在某些情况下很棒,但在其他情况下却很糟糕。
“this”的默认用法示例
让我们看一个涉及箭头函数和 this 关键字的示例:
// define an arrow function that prints the value of this keyword
const myFunc = () => {
console.log(this)
}
// call the function
myFunc()
在上面的代码中,创建了一个箭头函数,用于打印 this 关键字的值。然后调用该函数。在浏览器控制台中运行上述内容时,您将获得以下输出:
Window {0: Window, 1: Window, 2: Window, 3: Window, 4: Window, 5: Window, 6: Window, window: Window, self: Window, document: document, name: '', location: Location, …}
输出说明
您可以通过运行以下代码来验证上述代码的输出是否为 window 对象。
console.log(window)
这次的输出将是相同的,因为我们只是获取窗口对象。现在让我们理解为什么我们将 window 对象作为上述代码的输出,该代码涉及在箭头函数中使用 this 关键字。
如果您尝试使用普通函数执行操作,您仍然会得到一个窗口或全局对象。相同的结果,但原因不同。与箭头函数相反,普通函数的范围默认绑定到全局函数。另一方面,箭头函数没有自己的 this,而是从父作用域继承它。
现在让我们尝试一下如果我们使用严格模式会发生什么。
'use strict'
// define an arrow function that prints the value of this keyword
const myFunc = () => {
console.log(this)
}
// call the function
myFunc()
在上面的代码中,使用了严格模式,然后箭头函数与 this 关键字一起使用。运行它时,您将获得以下输出:
Window {0: Window, 1: Window, 2: Window, 3: Window, 4: Window, 5: Window, 6: Window, window: Window, self: Window, document: document, name: '', location: Location, …}
输出中没有更改,因为词法 this 的规则优先于严格模式此规则。
在箭头函数方法中使用“this”
常规函数将始终定义其此值。箭头函数对 this 关键字的处理方式不同。由于它缺乏自己的上下文,因此他们无法定义自己的上下文。每当调用 this 时,它们都会从父作用域获取 this 的值。
这始终是指在常规函数中调用的函数的上下文。但是,该函数的调用方与箭头函数中的此无关。它指的是函数所在的范围(封闭上下文)。因此,每当我们尝试从箭头函数方法访问对象属性的值时,我们都会收到未定义的值。这是因为这将引用全局变量。
以下对象具有箭头函数作为其方法。
const myObj = {
myMethod: () => {
console.log(this)
},
}
箭头函数将在调用它时记录 this 的值,如下所示:
myObj.myMethod()
输出将是窗口对象,因为这将引用全局对象。
箭头函数方法中“this”的示例
让我们举一个涉及具有箭头函数的对象的例子。
例
const myObject = {
fullname: 'John Doe',
sayName: () => {
return `My name is ${this.fullname}`
},
}
现在按以下方式调用该函数:
console.log(myObject.sayName())
您还可以使用以下代码来调用该函数:
const myMethod = myObject.sayName
console.log(myMethod())
在这两种方式中,输出将保持不变,即全局对象或窗口对象。这是因为与箭头函数中的普通函数不同,箭头函数的值不取决于函数的调用方式。
此外,箭头函数从父函数(在本例中为窗口或全局对象)继承其作用域,而不是绑定函数本身。
现在让我们对代码做一个小小的改动:
const myObject = {
fullname: 'John Doe',
myArrowFunction: null,
sayName: function () {
this.myArrowFunction = () => {
return `My name is ${this.fullname}`
}
},
}
myObject.sayName()
我们需要调用 myObject.sayName() 来初始化 myObject.myArrowFunction,然后就可以调用 myObject.myArrowFunction 了。
myObject.myArrowFunction() // this === myObject
您也可以通过以下方式调用该函数:
const myArrowFunction = myObject.myArrowFunction
myArrowFunction()
在上述两种方式中,输出将是:
'My name is John Doe'
当我们调用 myObject.myMethod() 函数时,我们使用 myMethod 方法内部的箭头函数初始化 myObject.myArrowFunction,因此它将继承 myMethod 函数的作用域。
在 API 调用中使用“this”
在进行 API 调用时,箭头函数是一个不错的选择,尤其是在使用闭包时。
示例 - 1 :
myObject = {
myMethod: function () {
helperObject.asyncOperation('apicall', () => {
console.log(this)
})
},
}
这是理想的情况,我们要求以异步方式完成某些操作,在采取任何进一步操作之前等待响应,并且我们不必担心请求的范围。
在上面的代码中,helperObject 是一些实例,它将有助于发出像 axios 这样的请求。上面代码中的 this 将引用 myObject。
如果我们在上面的代码中提取回调函数以使其可重用,如以下代码所示:
const reusabledCallback = () => {
console.log(this) // this === window or global object
}
myObject = {
myMethod: function () {
helperObject.asyncOperation('apiCall', reusabledCallback)
},
}
请记住,无论我们如何尝试绑定作用域,它都不会起作用,因此这样做意味着破坏当前功能代码。因此,如果选择这样做,则必须手动绑定范围并使用标准函数。
示例 - 2
const reusabledCallback = function () {
console.log(this)
}
myObject = {
myMethod: function () {
helperObject.asyncOperation('apiCall', reusabledCallback.bind(myObject))
},
}
解释:
现在,上面的代码将起作用,因为它的值将取决于调用可重用组件的方式。
结论
- JavaScript 中的 this 关键字是指对象。this 引用的对象携带当前正在运行的程序。
- 当引用常规函数时,它指的是全局对象。
- 对于事件,接收该事件的元素称为 this。
- call()、apply() 和 bind() 方法都可以使用它来引用任何对象。
- 常规函数将始终定义其此值。
- 箭头函数对 this 关键字的处理方式不同。由于它缺乏自己的上下文,因此他们无法定义自己的上下文。
- 这是基于箭头函数的封闭词法范围。
- 在常规函数中,调用函数的对象由 this 关键字表示。