Web 開發 16

1?在 JavaScript(包括 JSX)中,函數體的寫法和返回值處理

在 JavaScript(包括 JSX)中,函數體的寫法和返回值處理確實有一些簡潔的語法規則,尤其是在箭頭函數中。這些規則常常讓人混淆,我們來詳細梳理一下:

1. 首先明確:什么時候需要顯式?return

當函數體用?{}(花括號)包裹時,必須使用?return?才能返回值,否則默認返回?undefined

javascript

運行

// 普通函數
function add(a, b) {// 用了花括號,必須寫 returnreturn a + b;
}// 箭頭函數
const multiply = (a, b) => {// 用了花括號,必須寫 returnreturn a * b;
};

2. 什么時候可以省略?return(隱式返回)?

當函數體是「單行表達式」且沒有用?{}?包裹時,可以省略?return,箭頭函數會自動返回該表達式的結果。

這時有兩種寫法(效果相同):

  • 直接寫表達式(不加括號)
  • 用?()(圓括號)包裹表達式(推薦用于多行情況,如 JSX)

javascript

運行

// 情況1:單行表達式,不加括號
const subtract = (a, b) => a - b; 
// 等價于:(a,b) => { return a - b; }// 情況2:JSX 中常用圓括號(適合多行)
const User = (name) => (<div className="user"><h1>{name}</h1></div>
);
// 等價于:(name) => { return <div>...</div>; }

3. JSX 中的特殊情況

在 React 組件(JSX)中,箭頭函數的隱式返回非常常見,因為組件通常需要返回一段 JSX 結構。

錯誤示例(忘記?return?或括號):

jsx

// 錯誤1:用了花括號卻沒寫 return
const Button = () => {<button>點擊我</button> // 不會返回任何內容(返回 undefined)
};// 錯誤2:多行 JSX 沒加括號(解析會出錯)
const Card = () => <div className="card"><p>內容</p></div>; 
// 注意:如果 JSX 寫在一行可以不加括號,但多行必須加!
正確示例:

jsx

// 正確1:用花括號 + 顯式 return
const Button = () => {return <button>點擊我</button>;
};// 正確2:隱式返回(單行可省略括號)
const Avatar = (url) => <img src={url} alt="頭像" />;// 正確3:隱式返回(多行用圓括號包裹,推薦)
const Card = () => (<div className="card"><h2>標題</h2><p>內容</p></div>
);

總結規律:

函數體寫法是否需要?return適用場景
(參數) => { ... }是(必須寫)函數體有多行邏輯或需要條件判斷
(參數) => 表達式否(自動返回)單行簡單表達式
(參數) => ( ... )否(自動返回)多行表達式(如 JSX 結構)

簡單來說:花括號?{}?里要顯式?return,圓括號?()?或直接寫表達式則隱式返回

在 JSX 中,為了代碼清晰和避免錯誤,多行結構推薦用?()?包裹并省略?return

2?什么叫回調?

(這個概念很重要但是我總是沒有弄清楚)

“回調”(Callback)是 JavaScript 中非常重要的概念,簡單來說就是一個被作為參數傳遞給另一個函數的函數

當一個函數 A 被作為參數傳入函數 B,并且在函數 B 內部被調用執行時,A 就稱為 “回調函數”。

為什么需要回調?

JavaScript 中很多操作是 “異步” 的(比如讀取文件、網絡請求、定時器等),需要等某個操作完成后再執行后續邏輯,這時就需要用回調來 “等待并響應” 這個結果。

舉個生活例子:

你去餐廳吃飯,點餐后服務員給你一個叫號器(回調函數),告訴你 “做好了會叫你”。這里:

  • 服務員的 “通知” 行為就是調用回調函數
  • 你聽到叫號后去取餐的動作就是回調函數里的邏輯

代碼示例:

javascript

運行

// 定義一個回調函數:處理結果
function handleResult(result) {console.log("收到結果:", result);
}// 定義一個接收回調的函數
function doSomething(callback) {// 模擬一個耗時操作(比如網絡請求)setTimeout(() => {const result = "操作完成";// 操作完成后,調用回調函數并傳遞結果callback(result); }, 1000);
}// 調用:把 handleResult 作為回調傳入
doSomething(handleResult); 
// 1秒后會輸出:"收到結果:操作完成"

常見場景:

  1. 異步操作:定時器(setTimeout)、網絡請求(fetch)、文件讀取等

    javascript

    運行

    // 定時器回調
    setTimeout(() => {console.log("1秒后執行"); // 這是一個匿名回調函數
    }, 1000);
    
  2. 數組方法mapforEachfilter?等都需要傳入回調

    javascript

    運行

    const numbers = [1, 2, 3];
    // forEach 的參數就是一個回調函數
    numbers.forEach(num => console.log(num)); 
    
  3. 事件處理:DOM 事件或 React 事件中,事件處理函數本質也是回調

    jsx

    // React 中點擊事件的回調
    <button onClick={() => console.log("點擊了")}>點擊</button>
    

核心特點:

  • 回調函數是 “被別人調用” 的函數,不是自己主動執行
  • 常用于處理異步結果響應某個事件
  • 箭頭函數的簡寫形式讓回調代碼更簡潔(這也是之前提到的 “隱式回調” 的由來)

理解回調是學習 JavaScript 異步編程(如 Promise、async/await)的基礎~

3?嵌套函數(Nested Functions)

【函數里面套函數,一種類似于套娃的樣子?】

在 JavaScript 中,函數內部定義另一個函數的寫法非常常見,這種 “函數套函數” 的結構被稱為嵌套函數(Nested Functions),也確實像 “套娃” 一樣一層包一層。

為什么需要嵌套函數?

  1. 封裝邏輯:把只在當前函數內用到的邏輯 “藏” 在內部,避免污染外部作用域
  2. 訪問外部變量:內部函數可以直接接訪問外部函數的變量(閉包特性)
  3. 簡化代碼:減少全局函數的數量,讓邏輯更集中

基礎示例:簡單的嵌套函數

javascript

運行

function outerFunction() {const outerVar = "我是外部變量";// 內部嵌套的函數function innerFunction() {const innerVar = "我是內部變量";// 內部函數可以訪問外部函數的變量console.log(outerVar + "," + innerVar);}// 調用內部函數innerFunction();
}// 執行外部函數
outerFunction(); // 輸出:"我是外部變量,我是內部變量"

這里的?innerFunction?就是嵌套在?outerFunction?內部的函數,它只能在?outerFunction?內部被調用(除非被返回出去)。

進階場景:返回內部函數(閉包)

更強大的用法是讓外部函數返回內部函數,形成 “閉包”,這樣內部函數即使在外部函數執行完后,仍能訪問外部函數的變量:

javascript

運行

function createCounter() {let count = 0; // 這個變量被內部函數"記住"// 返回一個內部函數return function() {count++;return count;};
}// 得到內部函數
const counter = createCounter();// 多次調用,會持續累加
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

這里?createCounter?是外部函數,返回的匿名函數是內部函數。即使?createCounter?執行完了,內部函數依然能訪問并修改?count?變量,這就是閉包的特性。

JSX 中的嵌套函數(React 組件)

在 React 組件中,經常會在函數組件內部定義事件處理函數,也是嵌套函數的典型應用:

jsx

function UserProfile() {const [name, setName] = React.useState("");// 嵌套的事件處理函數function handleInputChange(e) {// 可以訪問外部的 name 和 setNamesetName(e.target.value);}return (<div><input type="text" value={name} onChange={handleInputChange} // 使用內部函數/><p>你輸入的是:{name}</p></div>);
}

handleInputChange?就是嵌套在?UserProfile?組件內部的函數,專門處理輸入框變化的邏輯。

注意點

  1. 作用域隔離:內部函數不能被外部直接訪問(除非被返回)
  2. 變量查找:內部函數會先找自己的變量,找不到再找外層函數的,直到全局(作用域鏈)
  3. 性能考量:過多的嵌套可能讓代碼可讀性下降,合理使用即可

這種 “套娃” 結構是 JavaScript 靈活性的體現,尤其是閉包特性,讓很多高級功能(如模塊化、私有變量)得以實現。

4?回調函數和嵌套函數

【上吊了,我以為這樣也算回調(原先把嵌套函數也誤以為是回調函數),應該是某個函數的參數也是一個函數,那么作為參數的那個函數也就是回調函數】

你的理解完全正確!當一個函數作為參數傳遞給另一個函數時,這個作為參數的函數就叫 “回調函數”,和 “函數套函數”(嵌套函數)是不同的概念,只是兩者有時會一起出現,容易混淆。

明確區分兩個概念:

  1. 嵌套函數:函數內部定義另一個函數(“套娃” 結構),重點是 “定義位置”

    javascript

    運行

    function outer() {// 這是嵌套函數(僅在 outer 內部定義)function inner() {} 
    }
    
  2. 回調函數:一個函數被作為參數傳給另一個函數(“參數身份”),重點是 “使用方式”

    javascript

    運行

    function callback() {}// 把 callback 作為參數傳給 doSomething,此時 callback 就是回調函數
    function doSomething(fn) { fn(); // 調用回調函數
    }doSomething(callback); 
    

為什么容易混淆?

因為回調函數經常會用匿名嵌套函數的形式寫,看起來像 “套娃”:

javascript

運行

// 匿名函數作為參數(回調),同時也是嵌套在 doSomething 調用中的
doSomething(function() { console.log("我是回調,也是匿名嵌套函數"); 
});

這里的匿名函數既是 “嵌套在調用語句中的函數”,也是 “作為參數的回調函數”,兩種身份重合了,所以容易讓人混淆。

一句話總結:

  • 嵌套函數:看 “是否定義在另一個函數內部”
  • 回調函數:看 “是否被當作參數傳給另一個函數”

你最初的理解是對的,“某個函數的參數也是一個函數,這個參數函數就是回調函數”,這是回調的核心定義~

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

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

相關文章

超高車輛碰撞預警系統如何幫助提升城市立交隧道安全?

超高車輛帶來的安全隱患立交橋和隧道的設計通常基于常規車輛的高度標準。然而&#xff0c;隨著重型運輸業和超高貨車的增加&#xff0c;很多超高車輛會誤入這些限高區域&#xff0c;造成潛在的安全隱患。超高車輛與立交橋梁或隧道頂蓋發生碰撞時&#xff0c;可能導致結構受損&a…

三種變量類型在局部與全局作用域的區別

一、基本概念作用域&#xff08;Scope&#xff09;&#xff1a; 全局作用域&#xff1a;定義在所有函數外部的變量或函數&#xff0c;具有文件作用域&#xff0c;生命周期為整個程序運行期間。局部作用域&#xff1a;定義在函數、塊&#xff08;如 {}&#xff09;或類內部的變量…

InfluxDB 數據遷移工具:跨數據庫同步方案(二)

六、基于 API 的同步方案實戰6.1 API 原理介紹InfluxDB 提供的 HTTP API 是實現數據遷移的重要途徑。通過這個 API&#xff0c;我們可以向 InfluxDB 發送 HTTP 請求&#xff0c;以實現數據的讀取和寫入操作。在數據讀取方面&#xff0c;使用GET請求&#xff0c;通過指定數據庫名…

JVM安全點輪詢匯編函數解析

OpenJDK 17 源碼的實現邏輯&#xff0c;handle_polling_page_exception 函數在方法返回時的調用流程如下&#xff1a;調用流程分析&#xff1a;棧水印檢查觸發跳轉&#xff1a;當線程執行方法返回前的安全點輪詢時&#xff08;MacroAssembler::safepoint_poll 中 at_returntrue…

Linux怎么查看服務器開放和啟用的端口

在 Linux 系統中&#xff0c;可以通過以下方法查看 服務器開放和啟用的端口。以下是詳細的步驟和工具&#xff0c;適用于不同場景。1. 使用 ss 查看開放的端口ss 是一個現代化工具&#xff0c;用于顯示網絡連接和監聽的端口。1.1 查看正在監聽的端口運行以下命令&#xff1a;ba…

XF 306-2025 阻燃耐火電線電纜檢測

近幾年隨著我國經濟快速的發展&#xff0c;電氣火災呈現高發趨勢&#xff0c;鑒于電線電纜火災的危險性&#xff0c;國家制定了阻燃&#xff0c;耐火電線電纜的標準&#xff0c;為企業&#xff0c;建設方&#xff0c;施工方等的生產&#xff0c;選材提供了指引。XF 306-2025 阻…

【Java|第二十篇】面向對象(十)——枚舉類

目錄 &#xff08;四&#xff09;面向對象&#xff1a; 12、枚舉類&#xff1a; &#xff08;1&#xff09;概述&#xff1a; &#xff08;2&#xff09;枚舉類的定義格式&#xff1a; &#xff08;3&#xff09;編譯與反編譯&#xff1a; &#xff08;4&#xff09;Enum類…

第二十一天-OLED顯示實驗

一、OLED顯示原理1、OLED名詞解釋OLED可以自發光&#xff0c;無需背光光源。2、正點原子OLED模塊模塊總體概述模塊接口模式選擇MCU與模塊外部連接8080并口讀寫過程OLED顯存因為要進行顯示&#xff0c;所以需要有顯存。顯存容量為128 x 8 byte&#xff0c;一個點用一位表示。SSD…

會議系統核心流程詳解:創建、加入與消息交互

一、系統架構概覽 會議系統采用"主進程線程池進程池"的分層架構&#xff0c;實現高并發與業務隔離&#xff1a; #mermaid-svg-fDJ5Ja5L3rqPkby0 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-fDJ5Ja5L3r…

Spring 創建 Bean 的 8 種主要方式

Spring&#xff08;尤其是 Spring Boot&#xff09;提供了多種方式來讓容器創建和管理 Bean。Component、Configuration Bean、EnableConfigurationProperties 都是常見方式。 下面我為你系統地梳理 Spring 創建 Bean 的所有主要方式&#xff0c;并說明它們的使用場景和區別。…

React 第七十節 Router中matchRoutes的使用詳解及注意事項

前言 matchRoutes 是 React Router v6 提供的一個核心工具函數&#xff0c;主要用于匹配路由配置與當前路徑。它在服務端渲染&#xff08;SSR&#xff09;、數據預加載、權限校驗等場景中非常實用。下面詳細解析其用法、注意事項和案例分析&#xff1a; 1、基本用法 import { m…

iSCSI服務配置全指南(含服務器與客戶端)

iSCSI服務配置全指南&#xff08;含服務器與客戶端&#xff09;一、iSCSI簡介 1. 概念 互聯網小型計算機系統接口&#xff08;Internet Small Computer System Interface&#xff0c;簡稱iSCSI&#xff09;是一種基于TCP/IP的協議&#xff0c;其核心功能是通過IP網絡仿真SCSI高…

堆(Heap):高效的優先級隊列實現

什么是堆&#xff1f;堆是一種特殊的完全二叉樹&#xff0c;滿足以下性質&#xff1a;堆序性&#xff1a;每個節點的值與其子節點滿足特定關系最小堆&#xff1a;父節點 ≤ 子節點&#xff08;根最小&#xff09;最大堆&#xff1a;父節點 ≥ 子節點&#xff08;根最大&#xf…

朝花夕拾(四) --------python中的os庫全指南

目錄 Python os模塊完全指南&#xff1a;從基礎到高階文件操作 1. 引言&#xff1a;為什么需要os模塊&#xff1f; 1.1 os模塊的重要性 1.2 適用場景 1.3 os模塊的"瑞士軍刀"特性 2. os模塊基礎功能 2.1 文件與目錄操作 2.1.1 核心方法介紹 2.1.2 避坑指南 …

uniappx 安卓端本地打包的一些總結

本人之前沒用過android studio&#xff0c;因為有打包到安卓端的需求&#xff0c;所以有了這篇文章。下面一些內容不正常工作&#xff0c;也不報錯&#xff0c;是很煩的&#xff0c;根本不知道是哪里出了問題。比如對應的aar包沒有引入。或者沒有注冊信息。 在實現過程中我遇到…

AUTOSAR進階圖解==>AUTOSAR_SWS_UDPNetworkManagement

AUTOSAR UDP網絡管理詳解 基于AUTOSAR標準的UDP網絡管理模塊架構分析與實現指南目錄 1. 概述2. UDP網絡管理架構 2.1 整體架構圖2.2 架構組件詳解 3. UDP網絡管理狀態機 3.1 狀態機圖3.2 狀態詳解 4. UDP網絡管理操作序列 4.1 序列圖4.2 操作流程詳解 5. UDP網絡管理配置模型 …

AI搜索引擎下的內容優化新范式:GEO的關鍵技術解析

摘要&#xff1a; 生成式AI搜索引擎的崛起&#xff0c;催生了GEO&#xff08;Generative Engine Optimization&#xff09;這一新的優化領域。本文將深入剖析GEO背后的關鍵技術&#xff0c;包括深度語義理解、結構化內容生成、以及AI算法的適配性&#xff0c;旨在為品牌在AI時代…

Java Lambda表達式是什么,怎么用

這種代碼是什么&#xff0c;怎么閱讀/*** 批量插入** param entityList ignore* param batchSize ignore* return ignore*/Transactional(rollbackFor Exception.class)Overridepublic boolean saveBatch(Collection<T> entityList, int batchSize) {String sqlStateme…

集成運算放大器(反向加法,減法)

反向加法電路原理&#xff1a;示波器顯示&#xff1a;結論&#xff1a;輸出電壓-&#xff08;R4/R1*V1R4/R2*V2R4/R3*V3&#xff09;。平衡電阻R4等于R1和R2和R3的并聯電壓。減法運算電路原理&#xff1a;結論&#xff1a;減法運算電路分為三種不同情況&#xff0c;第一種情況為…

Maven入門到精通

目錄 一&#xff0c;Maven概述 1.1介紹 1.2安裝 1.3Maven生命周期和插件 1.4Maven的坐標的本地倉庫的存儲地址 二&#xff0c;依賴管理 2.1依賴管理——依賴范圍 2.2依賴管理——添加依賴 獲取依賴坐標 依賴添加后的操作 2.3依賴管理——依賴傳遞 2.4依賴管理——依…