参加“this”测验,了解“this”在 JavaScript 中的工作原理

2025-05-25

参加“this”测验,了解“this”在 JavaScript 中的工作原理

在 JavaScript 提供的所有抽象概念中,“this”关键字可能是最难掌握的概念之一。从表面上看,“this”似乎是一个直观的关键字,仅仅指代它所处的环境(或上下文)。

当您深入了解 JavaScript 运行时(即代码执行的位置)时,“this”关键字最终可能会抓取您意想不到的东西。

在这篇文章中,我创建了 4 个简单的场景,其中“this”关键字可以有不同的解释,每个场景后面跟着一个多项选择部分、一个长时间的停顿(以防你滚动得太快而意外看到答案)以及带有解释的答案。

您可以在控制台或文本编辑器上随意尝试代码。记住,您遇到的情况越多、越多样化,您就越能识别和理解“this”关键字。

准备好了吗?我们开始

挑战#1

const call = {
  caller: "mom", 
  says: function() {
    console.log(`Hey, ${this.caller} just called.`);
  }
};

call.says();
Enter fullscreen mode Exit fullscreen mode

上面的代码将在控制台上输出什么?

(A)嘿,undefined 刚打来电话。
(B)嘿,妈妈刚打来电话。
(C)嘿,来电者刚打来电话。

...

...

...

...

...

...

...

...

...

...

答案是……

(B) 嘿,妈妈刚刚打电话来。

代码块如下:

const call = {
  caller: "mom", 
  says: function() {
    console.log(`Hey, ${this.caller} just called.`);
  }
};

call.says();
Enter fullscreen mode Exit fullscreen mode

这里我们在 call 对象内部有一个函数声明。一般来说,“this”由调用函数的对象决定。因此,当 call 对象调用 says 函数 (call.says()) 时, says 函数内部的“this”关键字指向 call 对象,因此 this.caller 等于 “mom”。

很简单,对吧?

挑战#2

const call = {
  caller: "mom", 
  says: () => {
    console.log(`Hey, ${this.caller} just called.`);
  }
};

call.says();
Enter fullscreen mode Exit fullscreen mode

上面的代码将在控制台上输出什么?

(A)嘿,undefined 刚打来电话。
(B)嘿,妈妈刚打来电话。
(C)嘿,来电者刚打来电话。

...

...

...

...

...

...

...

...

...

...

答案是……

(A) 嘿,undefined 刚刚打来电话。

代码块如下:

const call = {
  caller: "mom", 
  says: () => {
    console.log(`Hey, ${this.caller} just called.`);
  }
};

call.says();
Enter fullscreen mode Exit fullscreen mode

等等,这个代码不是和第一个一样吗?

如果仔细观察,就会发现挑战#1 中的函数声明现在已被箭头函数取代。

作为 ES6 语法的一部分,箭头函数没有自己的this关键字。相反,它们会使用函数创建时外部this的this关键字。

换句话说,箭头函数内的“this”并未绑定到我们的调用对象,而是已经绑定到最初创建调用对象的位置,在本例中是全局对象。 并且因为全局对象对 say() 函数一无所知,所以“this”是未定义的。而且由于全局对象没有 caller 属性,因此 this.caller 未定义。(感谢James Nylen的纠正!)

挑战#3

const call = {
  caller: "mom", 
  says: function() {
    console.log(`Hey, ${this.caller} just called.`);
  }
};

let newCall = call.says;

newCall();
Enter fullscreen mode Exit fullscreen mode

上面的代码将在控制台上输出什么?

(A) 嘿,undefined 刚刚打来电话。
(B) 嘿,妈妈刚刚打来电话。

...

...

...

...

...

...

...

...

...

...

答案是……

(A) 嘿,undefined 刚刚打来电话。

发生了什么?我们再看一下代码:

const call = {
  caller: "mom", 
  says: function() {
    console.log(`Hey, ${this.caller} just called.`);
  }
};

let newCall = call.says;

newCall();
Enter fullscreen mode Exit fullscreen mode

在这里,我们声明一个新变量,newCall并将 call 对象中的 says 函数赋值给newCall。然后我们调用newCall,这是一个简单的函数调用。

注意我们在哪里调用函数。它在调用对象内部吗?不是。我们全局调用 newCall() 函数,这使得this关键字等于全局对象。

正如挑战#2 中所示,由于全局对象没有调用者属性,因此结果为“未定义”。

现在,您可能会注意到一个关键模式:
常规函数根据调用该函数的对象改变其行为。

挑战#4

function anotherCaller() {
  console.log(`${this.caller} called, too!`);
}

const call = {
  caller: "mom", 
  anotherCaller: anotherCaller,
  says: function() {
    console.log(`Hey, ${this.caller} just called.`);
  }
};

let newCall = call.anotherCaller;

newCall();
Enter fullscreen mode Exit fullscreen mode

上面的代码将在控制台中记录什么?

(A) 妈妈也打来电话了!
(B) 嘿,妈妈刚刚打来电话了。
(C) undefined 也打来电话了!

...

...

...

...

...

...

...

...

...

...

答案是……

(C) undefined 也打来电话!

再次注意函数被调用的位置:

function anotherCaller() {
  console.log(`${this.caller} called, too!`);
}

const call = {
  caller: "mom", 
  anotherCaller: anotherCaller,
  says: function() {
    console.log(`Hey, ${this.caller} just called.`);
  }
};

let newCall = call.anotherCaller;

newCall();
Enter fullscreen mode Exit fullscreen mode

我们正在全局调用 newCall() 函数,这意味着'this'关键字指向的是全局对象。将 newCall 赋值给调用对象内部的函数并不重要。我们正在全局调用 newCall,而'this' 的赋值位置就在全局。

如果您喜欢冒险,请尝试将 anotherCaller() 函数移到调用对象内部,如下所示:

const call = {
  caller: "mom", 
  anotherCaller: function() {
        console.log(`${this.caller} called, too!`)
      },
  says: function() {
    console.log(`Hey, ${this.caller} just called.`);
  }
};


let newCall = call.anotherCaller;
newCall();
Enter fullscreen mode Exit fullscreen mode

根据我们刚才讨论的内容,您认为结果会是什么?

在浏览器中查看答案之前,先在心里默读一遍代码。如果你能理解,那你就掌握了至少掌握了基础知识)!


我希望这些示例能让你更好地理解“this”关键字的工作原理。如果你仍然感到困惑,不用担心。编程的一切,实践才是关键。

更多示例,请查看MDN 官方文档中关于 this 的内容。我也强烈推荐这篇很棒的文章。作者的解释清晰,实际上让我对上次挑战中遇到的一些棘手部分有了更深入的了解。

文章来源:https://dev.to/liaowow/take-this-quiz-understand-how-this-works-in-javascript-44dj
PREV
7分钟用JavaScript创建神经网络!简单理论 正向传播 反向传播(或反向传播,简称backprop) 实践 结论
NEXT
5 个适合视觉学习者的精美视觉资源