”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 为什么“this”关键字在常规函数和箭头函数中的行为不同

为什么“this”关键字在常规函数和箭头函数中的行为不同

发布于2024-07-30
浏览:165

Why the \

JavaScript 中的 this 关键字可能会令人困惑,因为它在常规函数和箭头函数中的行为不同。在这篇博文中,我们将解释这在两种类型的函数中如何工作,探讨为什么存在这些差异,并提供在 JavaScript 中理解这一点所需的基本知识。

常规功能

JavaScript 中的常规函数​​是使用 function 关键字定义的。这些函数中 this 的值取决于函数的调用方式。以下是几个例子:

1. 全球背景

  • 非严格模式:
  function regularFunction() {
      console.log(this);
  }

  regularFunction(); // Logs the global object (window in browsers)
  • 说明: 在非严格模式下,当在全局上下文中调用函数时(不是作为对象的方法),this 指的是全局对象(浏览器中的 window 或 Node 中的 global) .js).

    • 严格模式:
  'use strict';

  function regularFunction() {
      console.log(this);
  }

  regularFunction(); // Logs undefined
  • 说明:在严格模式下,当在全局上下文中调用函数时,this 保持未定义状态,通过防止意外修改全局对象来提供更安全的环境。

2. 方法调用

当函数作为对象的方法被调用时,this 引用该对象。

  • 例子:
  const obj = {
      method: function() {
          console.log(this);
      }
  };

  obj.method(); // Logs obj
  • 解释: 在本例中,this 指向 obj,因为该函数作为 obj 的方法被调用。

    • 严格模式:严格模式下的行为保持不变。

3. 构造函数调用

当函数用作构造函数(使用 new 关键字调用)时,this 指的是新创建的实例。

  • 例子:
  function Person(name) {
      this.name = name;
      this.sayHello = function() {
          console.log(`Hello, my name is ${this.name}`);
      };
  }

  const person1 = new Person('Alice');
  person1.sayHello(); // Logs "Hello, my name is Alice"

  const person2 = new Person('Bob');
  person2.sayHello(); // Logs "Hello, my name is Bob"
  • 说明: 当使用 new 调用时,Person 构造函数中的 this 指的是正在创建的新实例。每个新实例(person1 和 person2)都有自己的 name 属性和 sayHello 方法。

    • 严格模式:严格模式下的行为保持不变。

4. 显式绑定

您可以使用call、apply或bind显式绑定它。

  • 例子:
  function regularFunction() {
      console.log(this);
  }

  const obj = { value: 42 };

  regularFunction.call(obj);  // Logs obj
  regularFunction.apply(obj); // Logs obj

  const boundFunction = regularFunction.bind(obj);
  boundFunction();            // Logs obj
  • 说明: call 和 apply 立即调用将 this 设置为 obj 的函数,而 bind 创建一个新函数,并将 this 永久绑定到 obj。

    • 严格模式:严格模式下的行为保持不变。

箭头功能

ES6 中引入的箭头函数没有自己的 this 上下文。相反,它们从周围的(词法)范围继承这一点。这使得箭头函数在某些情况下很有用。

1. 词法 this

箭头函数从定义它们的作用域继承它。

  • 非严格模式:
  const arrowFunction = () => {
      console.log(this);
  };

  arrowFunction(); // Logs the global object (window in browsers)
  • 说明:箭头函数没有自己的this;他们从周围的范围内使用这个。这里,它指的是全局对象,因为该函数是在全局范围内定义的。

    • 严格模式:
  'use strict';

  const arrowFunction = () => {
      console.log(this);
  };

  arrowFunction(); // Logs undefined
  • 解释: 在严格模式下,如果周围作用域是全局的,则它保持未定义状态,因为从周围作用域继承。

2. 方法调用

与常规函数不同,箭头函数在作为方法调用时不会获得自己的 this。他们从封闭范围继承了这一点。

  • 例子:
  const obj = {
      method: () => {
          console.log(this);
      }
  };

  obj.method(); // Logs the global object (window in browsers) or undefined in strict mode
  • 说明:箭头函数不绑定自己的this,而是从词法作用域继承它。在这个例子中,this指的是全局对象或严格模式下的undefined,而不是obj.

    • 严格模式: 日志未定义,而不是 obj。

3.另一个函数内的箭头函数

当箭头函数在另一个函数内部定义时,它会从外部函数继承 this。

  • 例子:
  function outerFunction() {
      const arrowFunction = () => {
          console.log(this);
      };

      arrowFunction();
  }

  const obj = { value: 42, outerFunction: outerFunction };

  obj.outerFunction(); // Logs obj, because `this` in arrowFunction is inherited from outerFunction
  • 说明:此时,箭头函数内部的this指的是与outerFunction中相同的this,即obj.

    • 严格模式:严格模式下的行为保持不变。

4. 事件处理程序中的箭头函数

事件处理程序中的箭头函数从周围的词法范围继承此属性,而不是从触发事件的元素继承。

  • 例子:
  const button = document.querySelector('button');

  button.addEventListener('click', () => {
      console.log(this);
  }); // Logs the global object (window in browsers) or undefined in strict mode
  • 说明:箭头功能不将this绑定到按钮元素;它从周围的作用域继承它,该作用域是全局作用域或在严格模式下未定义。

    • 严格模式: 记录未定义的日志,而不是按钮元素。

为什么会有这些差异?

常规函数和箭头函数的区别在于它们的处理方式:

  • 常规函数: this 的值是动态的,由调用点(函数如何调用)决定。
  • 箭头函数: this 的值是词法的,并在定义函数时根据封闭执行上下文的 this 值进行设置。

需要理解的关键概念

要理解 JavaScript 中 this 的行为,您需要了解以下概念:

  1. 执行上下文: 代码执行的上下文,影响其确定方式。
  2. Call-site: 代码中调用函数的位置,影响常规函数中 this 的值。
  3. 词法作用域: this 如何在箭头函数中从周围作用域继承。
  4. 严格模式: 严格模式如何在某些上下文中改变 this 的默认行为。

概括

  • 常规函数:这是动态的,由调用站点决定。
  • 箭头函数: 这是词法的,由定义函数时的周围范围决定。

理解这些区别将帮助您编写更可预测和可维护的 JavaScript 代码。无论您使用常规函数还是箭头函数,了解其工作原理对于有效的 JavaScript 开发都至关重要。

版本声明 本文转载于:https://dev.to/hargun_singh/why-the-this-keyword-behaves-differently-in-regular-functions-and-arrow-functions-52j6?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 何时将成功回调函数与 jQuery Ajax 调用分离?
    何时将成功回调函数与 jQuery Ajax 调用分离?
    从 jQuery Ajax 调用解耦成功回调函数使用 jQuery ajax 从服务器检索数据时,通常的做法是定义成功.ajax() 块中的回调函数。这将回调处理与 AJAX 调用紧密结合在一起,限制了灵活性和可重用性。要在 .ajax() 块之外定义成功回调,通常需要声明一个用于存储返回数据的变量...
    编程 发布于2024-11-03
  • 极简设计初学者指南
    极简设计初学者指南
    我一直是干净和简单的倡导者——这是我的思维最清晰的方式。然而,就像生活中的大多数任务一样,不同的工作有不同的工具,设计也是如此。在这篇文章中,我将分享我发现的极简设计实践,这些实践有助于创建干净简单的网站、模板和图形——在有限的空间内传达必要的内容。 简单可能比复杂更难:你必须努力让你的思维清晰,使...
    编程 发布于2024-11-03
  • 了解 React 应用程序中的渲染和重新渲染:它们如何工作以及如何优化它们
    了解 React 应用程序中的渲染和重新渲染:它们如何工作以及如何优化它们
    当我们在 React 中创建应用程序时,我们经常会遇到术语渲染和重新渲染组件。虽然乍一看这似乎很简单,但当涉及不同的状态管理系统(如 useState、Redux)或当我们插入生命周期钩子(如 useEffect)时,事情会变得有趣。如果您希望您的应用程序快速高效,那么了解这些流程是关键。 ...
    编程 发布于2024-11-03
  • 如何在 Node.js 中将 JSON 文件读入服务器内存?
    如何在 Node.js 中将 JSON 文件读入服务器内存?
    在 Node.js 中将 JSON 文件读入服务器内存为了增强服务器端代码性能,您可能需要读取 JSON 对象从文件到内存以便快速访问。以下是在 Node.js 中实现此目的的方法:同步方法:对于同步文件读取,请利用 fs(文件系统)中的 readFileSync() 方法模块。此方法将文件内容作为...
    编程 发布于2024-11-03
  • 人工智能可以提供帮助
    人工智能可以提供帮助
    我刚刚意识到人工智能对开发人员有很大帮助。它不会很快接管我们的工作,因为它仍然很愚蠢,但是,如果你像我一样正在学习编程,可以用作一个很好的工具。 我要求 ChatGpt 为我准备 50 个项目来帮助我掌握 JavaScript,它带来了令人惊叹的项目,我相信当我完成这些项目时,这些项目将使我成为 J...
    编程 发布于2024-11-03
  • Shadcn UI 套件 - 管理仪表板和网站模板
    Shadcn UI 套件 - 管理仪表板和网站模板
    Shadcn UI 套件是预先设计的多功能仪表板、网站模板和组件的综合集合。它超越了 Shadcn 的标准产品,为那些不仅仅需要基础知识的人提供更先进的设计和功能。 独特的仪表板模板 Shadcn UI Kit 提供了各种精心制作的仪表板模板。目前,有 7 个仪表板模板可用,随着时间...
    编程 发布于2024-11-03
  • 如何使用正则表达式捕获多行文本块?
    如何使用正则表达式捕获多行文本块?
    匹配多行文本块的正则表达式匹配跨多行的文本可能会给正则表达式构造带来挑战。考虑以下示例文本:some Varying TEXT DSJFKDAFJKDAFJDSAKFJADSFLKDLAFKDSAF [more of the above, ending with a newline] [yep, t...
    编程 发布于2024-11-03
  • 软件开发中结构良好的日志的力量
    软件开发中结构良好的日志的力量
    日志是了解应用程序底层发生的情况的关键。 简单地使用 console.log 打印所有值并不是最有效的日志记录方法。日志的用途不仅仅是显示数据,它们还可以帮助您诊断问题、跟踪系统行为以及了解与外部 API 或服务的交互。在您的应用程序在没有用户界面的情况下运行的情况下,例如在系统之间处理和传输数据的...
    编程 发布于2024-11-03
  • 如何在单个命令行命令中执行多行Python语句?
    如何在单个命令行命令中执行多行Python语句?
    在单个命令行命令中执行多行Python语句Python -c 选项允许单行循环执行,但在命令中导入模块可能会导致语法错误。要解决此问题,请考虑以下解决方案:使用 Echo 和管道:echo -e "import sys\nfor r in range(10): print 'rob'&qu...
    编程 发布于2024-11-03
  • 查找数组/列表中的重复元素
    查找数组/列表中的重复元素
    给定一个整数数组,找到所有重复的元素。 例子: 输入:[1,2,3,4,3,2,5] 输出:[2, 3] 暗示: 您可以使用 HashSet 来跟踪您已经看到的元素。如果某个元素已在集合中,则它是重复的。为了保留顺序,请使用 LinkedHashSet 来存储重复项。 使用 HashSet 的 Ja...
    编程 发布于2024-11-03
  • JavaScript 回调何时异步?
    JavaScript 回调何时异步?
    JavaScript 回调:是否异步?JavaScript 回调并非普遍异步。在某些场景下,例如您提供的 addOne 和 simpleMap 函数的示例,代码会同步运行。浏览器中的异步 JavaScript基于回调的 AJAX 函数jQuery 中通常是异步的,因为它们涉及 XHR (XMLHtt...
    编程 发布于2024-11-03
  • 以下是根据您提供的文章内容生成的英文问答类标题:

Why does `char` behave differently from integer types in template instantiation when comparing `char`, `signed char`, and `unsigned char`?
    以下是根据您提供的文章内容生成的英文问答类标题: Why does `char` behave differently from integer types in template instantiation when comparing `char`, `signed char`, and `unsigned char`?
    char、signed char 和 unsigned char 之间的行为差​​异下面的代码可以成功编译,但 char 的行为与整数类型不同。cout << getIsTrue< isX<int8>::ikIsX >() << endl; cou...
    编程 发布于2024-11-03
  • 如何在动态生成的下拉框中设置默认选择?
    如何在动态生成的下拉框中设置默认选择?
    确定下拉框中选定的项目使用 标签创建下拉列表时,您可以可能会遇到需要将特定选项设置为默认选择的情况。这在预填写表单或允许用户编辑其设置时特别有用。在您呈现的场景中, 标记是使用 PHP 动态生成的,并且您希望根据值存储在数据库中。实现此目的的方法如下:设置选定的属性要在下拉框中设置选定的项目,您需...
    编程 发布于2024-11-03
  • Tailwind CSS:自定义配置
    Tailwind CSS:自定义配置
    介绍 Tailwind CSS 是一种流行的开源 CSS 框架,近年来在 Web 开发人员中广受欢迎。它提供了一种独特的可定制方法来创建美观且现代的用户界面。 Tailwind CSS 区别于其他 CSS 框架的关键功能之一是它的可定制配置。在这篇文章中,我们将讨论 Tailwin...
    编程 发布于2024-11-03
  • 使用 jQuery
    使用 jQuery
    什么是 jQuery? jQuery 是一个快速的 Javascript 库,其功能齐全,旨在简化 HTML 文档遍历、操作、事件处理和动画等任务。 “少写多做” MDN 状态: jQuery使得编写多行代码和tsk变得更加简洁,甚至一行代码.. 使用 jQuery 处理事件 jQuery 的另一个...
    编程 发布于2024-11-03

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3