箭頭函數(Arrow Functions)和普通函數(Regular Functions)

在 JavaScript 中,箭頭函數(Arrow Functions)和普通函數(Regular Functions)有以下主要區別:

1. 語法

  • 箭頭函數:使用?=>?語法,更簡潔,可省略?function?和?return(單行表達式時)。

    // 普通函數
    function add(a, b) { return a + b; }// 箭頭函數
    const add = (a, b) => a + b;
    
  • 普通函數:使用?function?關鍵字定義。

    function sayHello() {console.log("Hello");
    }
    

2.?this?指向

  • 箭頭函數

    • 不綁定?this,繼承自父級作用域(定義時的上下文)。
    • 適合不需要自己上下文的場景(如回調函數)。
    • const obj = {                      // 全局作用域(Global Scope)name: "Alice",                   // obj 對象作用域(Object Scope)greet: function() {              // greet 方法作用域(Function Scope)setTimeout(() => {             // 箭頭函數作用域(Arrow Function Scope)console.log(`Hello, ${this.name}`);}, 1000);}
      };
      obj.greet();

    • 箭頭函數的?this?繼承自哪里?
      箭頭函數的?this?繼承自它被定義時的外層作用域的?this(即?greet?函數的?this),而?不是?繼承外層函數(greet)本身。

      • greet?是一個普通函數,它的?this?由調用方式決定(obj.greet()?所以?this = obj)。

      • 箭頭函數繼承了?greet?的?this(即?obj),而不是?greet?函數對象。

    • 為什么不是指向?greet?函數?

      • 函數本身的?this?和函數對象是?完全不同的概念

      • greet?作為函數對象時,它的名字是?greet,但它的?this?是動態綁定的(這里是?obj)。

    const obj = {name: "Alice",greet: function() {setTimeout(() => {console.log(`Hello, ${this.name}`); // 繼承自 greet() 的 this}, 1000);}
    };
    obj.greet(); // "Hello, Alice"
    
  • 普通函數

    • 綁定自己的?this,指向調用該函數的對象(或全局對象 / 嚴格模式下為?undefined)。
    const obj = {name: "Bob",greet: function () {console.log(this.name); // "Bob"setTimeout(function () {console.log(`Hello, ${this.name}`); // this 指向全局對象或 undefined}, 1000);}
    };
    obj.greet(); // "Hello, undefined" 或報錯

  • const/let?聲明的全局變量?不會?成為全局對象(如?window)的屬性。

  • 只有?var?聲明的變量或直接賦值到?this?的屬性(如?window.age = 20)才會被?this.age?訪問到。

var age = 20; // var 會掛載到 window
/// const age = 20 //const 是局部變量
const obj = {greet: function() {setTimeout(function() {console.log(this.age); // 20(this 指向 window)}, 1000);}
};
obj.greet();

3.?arguments?對象

  • 箭頭函數

    • 沒有自己的?arguments?對象,繼承自父級作用域。
    const sum = () => {console.log(arguments); // 報錯或引用外層的 arguments
    };
    sum(1, 2); // 錯誤:arguments 未定義
    
  • 普通函數

    • 有自己的?arguments?對象,包含調用時的參數。
    function sum() {return arguments[0] + arguments[1];
    }
    sum(1, 2); // 3
    

4. 使用限制

  • 箭頭函數

    • 不能使用?argumentssuper?或?new.target
    • 不能使用?yield(不能用作生成器)。
    • 不能使用?new?實例化(沒有?[[Construct]]?方法)。
    const ArrowClass = () => {};
    new ArrowClass(); // 錯誤:箭頭函數不能用作構造函數
    
  • 普通函數

    • 可以使用?argumentssupernew.target?和?yield
    • 可以使用?new?實例化(作為構造函數)。
    function RegularClass() {this.value = 42;
    }
    const instance = new RegularClass();
    

5.?yield?和?await

  • 箭頭函數

    • 不能單獨使用?yield(除非在生成器函數內部)。
    • 可以使用?await,但需要在?async?箭頭函數中。
    const fetchData = async () => {const response = await fetch("api/data");return response.json();
    };
    
  • 普通函數

    • 可以使用?yield?定義生成器函數。
    function* generator() {yield 1;yield 2;
    }
    

6. 適用場景

  • 箭頭函數

    • 簡單的回調函數(如?mapfiltersetTimeout)。
    • 需要保留父級?this?的場景。
    • 單行邏輯的函數。
  • 普通函數

    • 構造函數(需要創建實例)。
    • 需要動態?this?綁定的場景(如方法、事件處理)。
    • 需要使用?arguments?對象的場景。

總結對比表

特性箭頭函數普通函數
語法簡潔,使用?=>完整,使用?function
this?指向繼承自父級作用域動態綁定(調用者)
arguments?對象
能否使用?new
能否使用?yield否(除非在生成器內)
適用場景回調函數、需要保留?this構造函數、動態?this?綁定

如何理解this 指向 箭頭函數的this繼承自父級作用域 普通函數的this是動態綁定(調用者)

要理解?this?指向的差異,關鍵在于抓住箭頭函數的?this?是 “靜態綁定”(定義時確定),而普通函數的?this?是 “動態綁定”(調用時確定)?這一核心區別。下面通過具體場景和例子展開說明:

一、箭頭函數:this?繼承自父級作用域(定義時確定)

箭頭函數沒有自己的?this,它的?this?是在定義函數時就固定好的,等于父級作用域(外層代碼塊)的?this,且永遠不會改變。

可以理解為:箭頭函數的?this?是 “抄” 父級的,一旦定義就 “鎖死”,后續無論怎么調用,this?都不會變。

例子 1:對象方法中的箭頭函數
const obj = {name: "Alice",// 普通函數作為方法(父級作用域)getParentThis: function() {// 箭頭函數定義在 getParentThis 內部,父級作用域是 getParentThis 的 thisconst arrowFunc = () => {console.log(this.name); // this 繼承自 getParentThis 的 this(即 obj)};return arrowFunc;}
};const func = obj.getParentThis(); 
func(); // 輸出 "Alice"(箭頭函數的 this 是定義時的父級 this,即 obj)

  • 箭頭函數?arrowFunc?定義在?getParentThis?內部,父級作用域的?this?是?obj(因為?getParentThis?是?obj?調用的),所以箭頭函數的?this?就是?obj
  • 即使后續用其他方式調用?func(如?func.call(otherObj)),this?也不會變,始終是?obj
例子 2:全局作用域中的箭頭函數
// 全局作用域的 this 是 window(瀏覽器環境)
const globalArrow = () => {console.log(this === window); // 輸出 true(繼承全局作用域的 this)
};globalArrow(); 
const obj = { fn: globalArrow };
obj.fn(); // 依然輸出 true(箭頭函數的 this 不會因調用者變化而改變)

二、普通函數:this?是動態綁定(調用時確定,由調用者決定)

普通函數的?this?是在調用函數時才確定的,取決于 “誰調用了它”,即 “調用者”。調用方式不同,this?指向就可能不同。

常見的調用場景決定?this?指向的規則:

  1. 直接調用(如?fn()):this?指向全局對象(瀏覽器中是?window,Node 中是?global;嚴格模式下為?undefined)。
  2. 作為對象方法調用(如?obj.fn()):this?指向該對象(obj)。
  3. 用?call/apply/bind?調用this?指向傳入的第一個參數。
  4. 作為構造函數調用(如?new Fn()):this?指向新創建的實例對象。
例子 1:不同調用方式下的普通函數?this
function regularFunc() {console.log(this.name);
}const obj1 = { name: "obj1" };
const obj2 = { name: "obj2" };// 1. 直接調用:this 指向全局(無 name 屬性,輸出 undefined)
regularFunc(); // undefined// 2. 作為對象方法調用:this 指向調用的對象
obj1.fn = regularFunc;
obj1.fn(); // 輸出 "obj1"(this 是 obj1)// 3. 用 call 強制綁定:this 指向傳入的 obj2
regularFunc.call(obj2); // 輸出 "obj2"
例子 2:對比箭頭函數和普通函數在回調中的差異

最典型的場景是定時器回調:

const person = {name: "Bob",// 普通函數作為方法sayHi: function() {// 1. 普通函數作為回調:this 指向全局(調用者是定時器,非 person)setTimeout(function() {console.log("普通函數回調:", this.name); // undefined(this 是 window)}, 100);// 2. 箭頭函數作為回調:this 繼承自 sayHi 的 this(即 person)setTimeout(() => {console.log("箭頭函數回調:", this.name); // "Bob"(this 是 person)}, 100);}
};person.sayHi(); 

  • 普通函數的回調:調用者是定時器(瀏覽器中是?window),所以?this?指向?window
  • 箭頭函數的回調:定義在?sayHi?內部,父級?sayHi?的?this?是?person,所以箭頭函數的?this?也是?person

總結:核心區別一句話

  • 箭頭函數this?是 “定義時抄父級的”,一旦確定就不變(靜態綁定)。
  • 普通函數this?是 “調用時看是誰調的”,調用方式變了,this?就可能變(動態綁定)。

記住這個區別,就能避開大多數?this?指向的坑。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/914385.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/914385.shtml
英文地址,請注明出處:http://en.pswp.cn/news/914385.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring Boot 配置注解處理器 - spring-boot-configuration-processor

前言 在 Spring Boot 開發中,配置屬性的管理是構建企業級應用的核心環節。Spring Boot 通過 ConfigurationProperties 注解提供了一種類型安全的方式,將配置文件中的屬性綁定到 Java 對象中。然而,開發者在使用過程中常會遇到配置屬性無自動補…

java: DDD using oracle 21c

項目結構:domain:/*** encoding: utf-8* 版權所有 2025 ©涂聚文有限公司 * 許可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎* 描述:* Author : geovindu,Geovin Du 涂聚文.* IDE : IntelliJ IDEA 2024…

兩張圖片對比clip功能

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>圖片拖動Clip對比功能</title><style&g…

7.11 dp 圖

lcr148.棧按放入順序推棧&#xff0c;能彈出的就及時彈出&#xff0c;最后棧空則符合要求。判斷 takeOut 序列是否符合棧的操作邏輯&#xff0c;因為題目中“特殊的數據結構”其實就是棧&#xff08;先進后出&#xff09;。思路如下&#xff1a;1. 用一個棧來模擬圖書放入的過程…

react16-react19都更新哪些內容?

React 16 到 React 19 是 React 發展非常關鍵的階段&#xff0c;每個版本都帶來了深遠影響。以下是 React 16 → 19 的重要更新列表&#xff0c;按版本詳細說明每一代的核心特性、重要變化、對開發者的意義&#xff0c;并附簡評&#xff1a;? React 16&#xff08;2017 年&…

【AI大模型】RAG系統組件:向量數據庫(ChromaDB)

RAG 系統中的關鍵組件&#xff1a;向量數據庫&#xff08;Vector Database&#xff09;&#xff0c;并以 ChromaDB 為例進行說明。什么是向量數據庫&#xff1f;核心概念&#xff1a; 向量數據庫是一種專門設計用于高效存儲、索引和檢索高維向量的數據庫。向量是什么&#xff1…

006_測試評估與安全實踐

測試評估與安全實踐 目錄 建立成功標準評估方法測試策略安全最佳實踐隱私保護性能監控 建立成功標準 定義原則 1. 具體明確 清晰定義精確目標避免模糊表述如"良好性能"制定可操作的標準 不好的標準&#xff1a; 模型應該表現良好好的標準&#xff1a; 情感分…

時序預測 | Pytorch實現CNN-KAN電力負荷時間序列預測模型

預測效果 代碼功能 該代碼實現了一個結合卷積神經網絡&#xff08;CNN&#xff09;和Kolmogorov–Arnold網絡&#xff08;KAN&#xff09;的混合模型&#xff08;CNN-KAN&#xff09;&#xff0c;用于時間序列預測任務。核心功能包括&#xff1a; 數據加載與預處理&#xff1…

UI前端與數字孿生結合實踐探索:智慧物流的倉儲優化與管理系統

hello寶子們...我們是艾斯視覺擅長ui設計和前端數字孿生、大數據、三維建模、三維動畫10年經驗!希望我的分享能幫助到您!如需幫助可以評論關注私信我們一起探討!致敬感謝感恩!一、引言&#xff1a;倉儲管理的 “數字孿生革命”傳統物流倉儲正面臨 “效率瓶頸、可視化差、響應滯…

【Android】在平板上實現Rs485的數據通訊

前言 在工業控制領域&#xff0c;Android 設備通過 RS485 接口與 PLC&#xff08;可編程邏輯控制器&#xff09;通信是一種常見的技術方案。最近在實現一個項目需要和plc使用485進行通訊&#xff0c;記錄下實現的方式。 我這邊使用的從平的Android平板&#xff0c;從平里面已經…

MySQL技術筆記-備份與恢復完全指南

目錄 前言 一、備份概述 &#xff08;一&#xff09;備份方式 &#xff08;二&#xff09;備份策略 二、物理備份及恢復 &#xff08;一&#xff09;備份操作 &#xff08;二&#xff09;恢復操作 三、邏輯備份及恢復 &#xff08;一&#xff09;邏輯備份 &#xff0…

SpringBoot或OpenFeign中 Jackson 配置參數名蛇形、小駝峰、大駝峰、自定義命名

SpringBoot或OpenFeign中 Jackson 配置參數名蛇形、小駝峰、大駝峰、自定義命名 前言 在調用外部接口時&#xff0c;對方給出的接口文檔中&#xff0c;入參參數名一會大寫加下劃線&#xff0c;一會又是駝峰命名。 示例如下&#xff1a; {"MOF_DIV_CODE": "xx…

uni-app 途徑站點組件開發與實現分享

在移動應用開發中&#xff0c;涉及到出行、物流等場景時&#xff0c;途徑站點的展示是一個常見的需求。本文將為大家分享一個基于 uni-app 開發的途徑站點組件&#xff0c;該組件能夠清晰展示路線中的各個站點信息&#xff0c;包括站點名稱、到達時間、是否已到達等狀態&#x…

kotlin中集合的用法

從一個實際應用看起以下kotlin中代碼語法正確嗎 var testBeanAIP0200()var testList:List<AIP0200> ArrayList()testList.add(testBean)這段Kotlin代碼存在語法錯誤&#xff0c;主要問題在于&#xff1a;List<AIP0200> 是Kotlin中的不可變集合接口&#xff0c;不能…

深入理解 Java Map 與 Set

文章目錄前言1. 搜索樹1.1 什么是搜索樹1.2 查找1.3 插入1.4 刪除情況一&#xff1a;cur 沒有子節點&#xff08;即為葉子節點&#xff09;情況二&#xff1a;cur 只有一個子節點&#xff08;只有左子樹或右子樹&#xff09;情況三&#xff1a;cur 有兩個子節點&#xff08;左右…

excel如何只保留前幾行

方法一&#xff1a;手動刪除多余行 選中你想保留的最后一行的下一行&#xff08;比如你只保留前10行&#xff0c;那選第11行&#xff09;。按住 Shift Ctrl ↓&#xff08;Windows&#xff09;或 Shift Command ↓&#xff08;Mac&#xff09;&#xff0c;選中從第11行到最…

實時連接,精準監控:風丘科技數據遠程顯示方案提升試驗車隊管理效率

風丘科技推出的數據遠程實時顯示方案更好地滿足了客戶對于試驗車隊遠程實時監控的需求&#xff0c;并真正實現了試驗車隊的遠程管理。隨著新的數據記錄儀軟件IPEmotion RT和相應的跨平臺顯示解決方案的引入&#xff0c;讓我們的客戶端不僅可在線訪問記錄器系統狀態&#xff0c;…

灰盒級SOA測試工具Parasoft SOAtest重新定義端到端測試

還在為脆弱的測試環境、強外部依賴和低效的測試復用拖慢交付而頭疼&#xff1f;尤其在銀行、醫療、制造等關鍵領域&#xff0c;傳統的端到端測試常因環境不穩、接口難模擬、用例難共享而舉步維艱。 灰盒級SOA測試工具Parasoft SOAtest以可視化編排簡化復雜測試流程&#xff0c…

OKHttp 核心知識點詳解

OKHttp 核心知識點詳解 一、基本概念與架構 1. OKHttp 簡介 類型&#xff1a;高效的HTTP客戶端特點&#xff1a; 支持HTTP/2和SPDY&#xff08;多路復用&#xff09;連接池減少請求延遲透明的GZIP壓縮響應緩存自動恢復網絡故障2. 核心組件組件功能OkHttpClient客戶端入口&#…

從“被動巡檢”到“主動預警”:塔能物聯運維平臺重構路燈管理模式

從以往的‘被動巡檢’轉變至如今的‘主動預警’&#xff0c;塔能物聯運維平臺對路燈管理模式展開了重新構建。城市路燈屬于極為重要的市政基礎設施范疇&#xff0c;它的實際運行狀態和市民出行安全以及城市形象有著直接且緊密的關聯。不過呢&#xff0c;傳統的路燈管理模式當下…