」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 為什麼「this」關鍵字在常規函數和箭頭函數中的行為不同

為什麼「this」關鍵字在常規函數和箭頭函數中的行為不同

發佈於2024-07-30
瀏覽:552

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如有侵犯,請聯絡study_golang@163 .com刪除
最新教學 更多>
  • 如何在 PHP 中組合兩個關聯數組,同時保留唯一 ID 並處理重複名稱?
    如何在 PHP 中組合兩個關聯數組,同時保留唯一 ID 並處理重複名稱?
    在 PHP 中組合關聯數組在 PHP 中,將兩個關聯數組組合成一個數組是常見任務。考慮以下請求:問題描述:提供的代碼定義了兩個關聯數組,$array1和$array2。目標是建立一個新陣列 $array3,它合併兩個陣列中的所有鍵值對。 此外,提供的陣列具有唯一的 ID,而名稱可能重疊。要求是建構一...
    程式設計 發佈於2024-12-20
  • 在 Go 中使用 WebSocket 進行即時通信
    在 Go 中使用 WebSocket 進行即時通信
    构建需要实时更新的应用程序(例如聊天应用程序、实时通知或协作工具)需要一种比传统 HTTP 更快、更具交互性的通信方法。这就是 WebSockets 发挥作用的地方!今天,我们将探讨如何在 Go 中使用 WebSocket,以便您可以向应用程序添加实时功能。 在这篇文章中,我们将介绍: WebSoc...
    程式設計 發佈於2024-12-20
  • 插入資料時如何修復「常規錯誤:2006 MySQL 伺服器已消失」?
    插入資料時如何修復「常規錯誤:2006 MySQL 伺服器已消失」?
    插入記錄時如何解決「一般錯誤:2006 MySQL 伺服器已消失」介紹:將資料插入MySQL 資料庫有時會導致錯誤「一般錯誤:2006 MySQL 伺服器已消失」。當與伺服器的連線遺失時會出現此錯誤,通常是由於 MySQL 配置中的兩個變數之一所致。 解決方案:解決此錯誤的關鍵是調整wait_tim...
    程式設計 發佈於2024-12-20
  • 儘管程式碼有效,為什麼 POST 請求無法擷取 PHP 中的輸入?
    儘管程式碼有效,為什麼 POST 請求無法擷取 PHP 中的輸入?
    解決PHP 中的POST 請求故障在提供的程式碼片段:action=''而非:action="<?php echo $_SERVER['PHP_SELF'];?>";?>"檢查$_POST陣列:表單提交後使用 var_dump 檢查 $_POST 陣列的內容...
    程式設計 發佈於2024-12-20
  • Bootstrap 4 Beta 中的列偏移發生了什麼事?
    Bootstrap 4 Beta 中的列偏移發生了什麼事?
    Bootstrap 4 Beta:列偏移的刪除和恢復Bootstrap 4 在其Beta 1 版本中引入了重大更改柱子偏移了。然而,隨著 Beta 2 的後續發布,這些變化已經逆轉。 從 offset-md-* 到 ml-auto在 Bootstrap 4 Beta 1 中, offset-md-*...
    程式設計 發佈於2024-12-20
  • 大批
    大批
    方法是可以在物件上呼叫的 fns 數組是對象,因此它們在 JS 中也有方法。 slice(begin):將陣列的一部分提取到新數組中,而不改變原始數組。 let arr = ['a','b','c','d','e']; // Usecase: Extract till index ...
    程式設計 發佈於2024-12-20
  • 如何在 AngularJS 中有效地求和數組屬性?
    如何在 AngularJS 中有效地求和數組屬性?
    AngularJS 中的高級數組求和在 AngularJS 中,對數組屬性求和可能是一項常見任務。基本方法包括迭代數組並累積屬性值。然而,當面對多個陣列和不同的屬性名稱時,這種方法變得乏味。 為了解決這個問題,需要一個更靈活、可重複使用的解決方案,它允許對任何陣列屬性進行方便的求和。這可以使用 re...
    程式設計 發佈於2024-12-20
  • 如何在不進行按引用修改的情況下高效檢索第一個數組元素?
    如何在不進行按引用修改的情況下高效檢索第一個數組元素?
    在不透過引用操作的情況下檢索數組的第一個元素獲取數組的第一個元素可能是編程中的常見任務。雖然有多種方法可以實現這一點,但重要的是要考慮不使用引用操作的約束,就像 array_shift 的情況一樣。本文探討了在 PHP 中實現此目標的幾種有效方法。 O(n) 方法:一種方法是使用 array_val...
    程式設計 發佈於2024-12-20
  • C++ 函式宣告中「const」的真正意義是什麼?
    C++ 函式宣告中「const」的真正意義是什麼?
    解密返回類型、函數參數和成員函數中的Const 關鍵字C 程式碼片段中:const int* const Method3(const int* const&amp;) const;the術語“const”出現多次,每次都有特定含義。 1.傳回型別中的 Const(指向 Int Const 的...
    程式設計 發佈於2024-12-20
  • 使用“list.List”是建立帶有字串鍵和列表值的 Go 映射的最佳方法嗎?
    使用“list.List”是建立帶有字串鍵和列表值的 Go 映射的最佳方法嗎?
    建立字串到清單的對應問題:您想要建立一個有字串型別鍵的映射和列表類型的值。以下程式碼片段是否是正確的方法:package main import ( "fmt" "container/list" ) func main() { x :=...
    程式設計 發佈於2024-12-19
  • 使用 html css 和 javascript 幻覺的 Tic-Tac-Toe 遊戲 https://www.instagram.com/webstreet_code/
    使用 html css 和 javascript 幻覺的 Tic-Tac-Toe 遊戲 https://www.instagram.com/webstreet_code/
    在 Instagram 上關注我們:https://www.instagram.com/webstreet_code/ ? ✨ 有玻璃效果的井字遊戲! ✨? 我剛剛使用 HTML、CSS 和 JavaScript 構建了一款經典的 Tic-Tac-Toe 遊戲,具有時尚的玻璃態設計。觀看視頻,看看...
    程式設計 發佈於2024-12-19
  • TB 級資料庫的 MySQL 與 NoSQL:聚集索引何時是正確的解決方案?
    TB 級資料庫的 MySQL 與 NoSQL:聚集索引何時是正確的解決方案?
    MySQL:探索資料庫設計迷宮優化大型資料庫時,必須考慮資料庫設計策略以提高效能。在給定的場景中,包含執行緒的 TB 級資料庫由於其龐大的規模而面臨效能挑戰。本文探討了 MySQL 和 NoSQL 之間的選擇,重點介紹了 MySQL 的 innodb 引擎及其聚集索引的優點。 了解 MySQL 的 ...
    程式設計 發佈於2024-12-19
  • 為什麼我的 Spring Boot 應用程式不自動建立資料庫架構?
    為什麼我的 Spring Boot 應用程式不自動建立資料庫架構?
    在 Spring Boot 中自動建立資料庫架構啟動 Spring Boot 應用程式時,可能會遇到自動建立資料庫架構的問題。以下故障排除步驟旨在解決此問題:1.實體類別包:確保實體類別位於使用@EnableAutoConfiguration註解的類別的同一個套件或子包中。否則,Spring 將不會...
    程式設計 發佈於2024-12-18
  • CSS3 轉場是否提供事件來偵測起點和終點?
    CSS3 轉場是否提供事件來偵測起點和終點?
    了解 CSS3 過渡事件CSS3 過渡允許在 Web 元素上實現流暢的動畫和視覺效果。為了增強使用者體驗並使操作與這些轉換同步,監控其進度非常重要。本文解決了 CSS3 是否提供事件來檢查過渡何時開始或結束的問題。 W3C CSS 過渡草案W3C CSS 過渡草案規定CSS 轉換會觸發對應的 DOM...
    程式設計 發佈於2024-12-18
  • Java 中可以手動釋放記憶體嗎?
    Java 中可以手動釋放記憶體嗎?
    Java 中的手動內存釋放與垃圾回收與C 不同,Java 採用託管內存框架來處理內存分配和釋放由垃圾收集器(GC) 自動執行。這種自動化方法可以提高記憶體利用率並防止困擾 C 程式的記憶體洩漏。 Java 中可以手動釋放記憶體嗎? 由於 Java 的記憶體管理是由GC,它沒有提供像 C 中的 fre...
    程式設計 發佈於2024-12-18

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3