学习 React 前,你必须掌握的 10 个 JavaScript 核心概念

学习 React 前,你必须掌握的 10 个 JavaScript 核心概念

如果你正计划入门 React.js,先稍等一下 —— 问问自己:“我的 JavaScript 基础真的扎实吗?”

React 并非写过几行 JS 就能直接上手的框架。它要求你清楚 JavaScript 的底层工作原理,尤其是那些看似简单、却支撑着整个 React 生态的核心概念。

下面就为大家详细拆解,每个 React 开发者在写出第一个 JSX 之前,必须掌握的 10 个 JavaScript 核心概念。

🔹 1. let、const 与 var

在 React 中,你会频繁声明变量。但如果使用不当,很容易引发难以排查的 bug。理解这三者的作用域规则、重声明限制以及暂时性死区,能帮你节省大量调试时间。

示例:三者的区别与应用场景

// var:函数级/全局作用域,存在变量提升,可重复声明
console.log(name); // 输出 undefined(变量提升但未赋值)
var name = "张三";
function testVar() {var name = "李四"; // 函数内重声明,不影响外部console.log(name); // 输出 李四
}
testVar();
console.log(name); // 输出 张三
// let:块级作用域,无变量提升,存在暂时性死区,不可重复声明
console.log(age); // 报错(暂时性死区,无法访问未初始化的let变量)
let age = 25;
if (true) {let age = 30; // 块内声明,不影响外部console.log(age); // 输出 30
}
console.log(age); // 输出 25
// const:块级作用域,必须初始化,不可重新赋值(引用类型内部可修改)
const PI = 3.14159;
PI = 3.14; // 报错(常量不可重新赋值)
const user = { name: "王五" };
user.name = "赵六"; // 可行(引用类型内部属性可修改)
console.log(user.name); // 输出 赵六

🔹 2. 变量提升(Hoisting)

React 组件本质就是 JavaScript 函数。但如果不理解变量提升,你常会遇到 “变量还没使用就报错” 的困惑 —— 这其实是提升机制在背后起作用。

示例:变量提升的表现与注意点

// 函数声明会整体提升,可在声明前调用
sayHello(); // 输出 Hello!
function sayHello() {console.log("Hello!");
}
// var声明的变量仅提升“声明”,不提升“赋值”
console.log(num); // 输出 undefined(声明提升,赋值未提升)
var num = 10;
console.log(num); // 输出 10
// let/const 无变量提升,存在暂时性死区
console.log(str); // 报错(无法访问未初始化的let变量)
let str = "test";

🔹 3. 闭包(Closures)

闭包不只是面试题考点 —— 它是 React Hooks(尤其是useState、useEffect)和事件处理的核心动力。没有闭包,React 的状态保存与行为逻辑几乎无法实现。

示例:闭包在 React 中的实际应用

// 闭包基础:内部函数访问外部函数变量,变量不会被销毁
function createCounter() {let count = 0; // 外部函数变量,被内部函数引用return function () {count++;return count;};
}
const counter = createCounter();
console.log(counter()); // 输出 1
console.log(counter()); // 输出 2(count状态被保留)
// React中闭包的典型场景:useState依赖闭包保存状态
import { useState } from "react";
function CounterComponent() {const [count, setCount] = useState(0);// 事件处理函数通过闭包访问count状态const handleIncrement = () =&gt; {setCount(count + 1); // 此处能访问count,正是闭包的作用};return <button onclick="{handleIncrement}">计数:{count}</button>;
}

🔹 4. 回调函数(Callback Functions)

React 严重依赖回调函数 —— 从事件处理(onClick)到副作用管理(useEffect)都离不开它。掌握 “如何传递函数”“如何延迟执行” 以及 “如何避免回调地狱”,是 React 开发的基础。

示例:React 中的回调函数与优化

// 1. 事件处理中的回调函数
function Button() {// 回调函数:点击时才执行const handleClick = () =&gt; {console.log("按钮被点击");};// onClick接收回调函数,不立即执行return <button onclick="{handleClick}">点击我</button>;
}
// 2. 避免回调地狱:用async/await优化异步请求
async function getUserOrders() {try {// 第一步:获取用户信息const userRes = await fetch("/api/user");const user = await userRes.json();// 第二步:获取用户订单(无需嵌套)const ordersRes = await fetch(`/api/user/${user.id}/orders`);const orders = await ordersRes.json();console.log("用户订单:", orders);} catch (error) {console.error("请求失败:", error);}
}

🔹 5. Promise 与 Async/Await

在 React 中,调用 API 获取数据是日常操作(如用fetch或国内常用的axios)。掌握 Promise 与 async/await,能让你写出不阻塞浏览器的异步代码,避免页面 “卡死”。

示例:结合 axios 的异步数据请求(国内常用场景)

import { useState, useEffect } from "react";
import axios from "axios"; // 国内常用的HTTP库
function DataComponent() {const [userData, setUserData] = useState(null);const [loading, setLoading] = useState(false);// 用async/await封装异步请求const fetchUserData = async () =&gt; {setLoading(true);try {// 示例:请求掘金用户接口(需处理跨域,实际项目需后端代理)const res = await axios.get("https://api.juejin.cn/user_api/v1/user/get");setUserData(res.data.data); // 赋值返回的用户数据} catch (error) {console.error("数据获取失败:", error);} finally {setLoading(false); // 无论成功失败,都结束加载状态}};// 组件挂载时执行请求useEffect(() =&gt; {fetchUserData();}, []);// 加载状态与数据展示return loading ? (<div>加载中...</div>) : (<div>欢迎,{userData?.user_name || "游客"}</div>);
}

🔹 6. 数组方法(map、filter、reduce)

React 开发围绕数组展开:用map渲染列表、用filter筛选数据、用reduce统计信息 —— 这些方法能让你的 UI 逻辑更简洁高效。

示例:React 中数组方法的高频用法

import { useState } from "react";
function UserList() {const [users, setUsers] = useState([{ id: 1, name: "张三", age: 16, isVip: false },{ id: 2, name: "李四", age: 20, isVip: true },{ id: 3, name: "王五", age: 22, isVip: true },]);// 1. map:渲染列表(React必用,需加key)const userItems = users.map((user) =&gt; (<li key="{user.id}">{user.name}({user.age}岁){user.isVip ? "[VIP]" : ""}</li>));// 2. filter:筛选VIP用户const vipUsers = users.filter((user) =&gt; user.isVip);// 3. reduce:计算用户平均年龄const avgAge = users.reduce((sum, user) =&gt; sum + user.age, 0) / users.length;return (<div><h3>所有用户</h3><ul>{userItems}</ul><p>VIP用户数:{vipUsers.length}</p><p>平均年龄:{avgAge.toFixed(1)}</p></div>);
}

🔹 7. 解构(Destructuring)

在 React 中,从props或state中提取值时,解构能让代码更简洁易读 —— 尤其在函数组件中,几乎是 “标配” 写法。

示例:React 中的解构应用

// 1. 解构props(最常用场景)
// 未解构:代码冗长
function Greeting(props) {return <h1>你好,{props.name}!年龄:{props.age}</h1>;
}
// 解构:简洁清晰
function Greeting({ name, age }) {return <h1>你好,{name}!年龄:{age}</h1>;
}
// 2. 解构state
import { useState } from "react";
function Profile() {const [user, setUser] = useState({name: "张三",address: "北京",phone: "138****1234",});// 从user中解构需要的属性const { name, address } = user;return <div>{name} 住在 {address}</div>;
}
// 3. 数组解构(配合useState)
const [count, setCount] = useState(0); // 解构useState返回的数组

🔹 8. 扩展与剩余运算符(Spread & Rest Operators)

这两个运算符在 React 中高频出现:处理props传递、更新状态、合并对象等场景都能用到,极大简化了数据操作逻辑。

示例:React 中的运算符应用

// 1. 扩展运算符(...):传递所有props
function Parent() {const user = { name: "张三", age: 25, gender: "男" };// 用...将user的所有属性传递给Child,无需逐个写propsreturn <child {...user} />;
}
function Child({ name, age, gender }) {return <div>{name},{age}岁,{gender}</div>;
}
// 2. 扩展运算符:更新React状态(不可直接修改原状态)
import { useState } from "react";
function Profile() {const [profile, setProfile] = useState({name: "张三",age: 25,});// 只更新age,保留其他属性(正确写法)const updateAge = () =&gt; {setProfile({ ...profile, age: 26 }); // ...profile复制原有属性};return (<div><p>年龄:{profile.age}</p><button onclick="{updateAge}">增加年龄</button></div>);
}
// 3. 剩余运算符(...):收集多个参数
function sum(...numbers) {// numbers是一个数组,包含所有传入的参数return numbers.reduce((total, num) =&gt; total + num, 0);
}
console.log(sum(1, 2, 3)); // 输出 6

🔹 9. 真值与假值(Truthy and Falsy Values)

React 的条件渲染完全依赖 JavaScript 的真值 / 假值判断。理解 “哪些值被视为 true,哪些被视为 false”,能帮你避免 UI 渲染异常(如空数组显示 “有数据”)。

示例:条件渲染中的真值 / 假值应用

// JavaScript中的假值(仅6个):false、0、""、null、undefined、NaN
// 其他值均为真值(包括 "0"、{}、[]、true 等)
import { useState } from "react";
function LoginStatus() {const [user, setUser] = useState(null); // 未登录时为null(假值)// 条件1:用户登录(user为真值)显示欢迎语// 条件2:用户未登录(user为假值)显示登录按钮return user ? (<div>欢迎,{user.name}!</div>) : (<button onclick="{()" => setUser({ name: "张三" })}&gt;登录</button>);
}
// 注意:空数组[]是真值,需判断长度
function List({ data }) {// 错误:data为[]时,if(data)为true,会显示“有数据”// if (data) return <div>有数据</div>;// 正确:判断数组长度if (data.length &gt; 0) {return <div>有数据:{data.map(item =&gt; <p key="{item.id}">{item.name}</p>)}</div>;}return <div>无数据</div>;
}

🔹 10. DOM 与事件(基础)

React 虽然封装了 DOM(虚拟 DOM),但仍需与原生 DOM 交互。理解基础的 DOM 操作和原生事件,能帮你搞懂 React 合成事件的底层逻辑,避免 “事件绑定失效” 等问题。

示例:原生 DOM 与 React 合成事件对比

// 1. 原生DOM操作(理解原理)
// HTML:<button id="nativeBtn">原生按钮</button>
const nativeBtn = document.getElementById("nativeBtn");
nativeBtn.addEventListener("click", () =&gt; {console.log("原生按钮被点击");
});
// 2. React合成事件(开发常用)
import { useState } from "react";
function ReactButton() {const [count, setCount] = useState(0);// React合成事件:onClick(驼峰命名,区别于原生onclick)const handleClick = (e) =&gt; {setCount(count + 1);// e是React合成事件对象,可通过e.nativeEvent获取原生事件console.log("原生事件对象:", e.nativeEvent);};// React自动管理事件解绑,无需手动移除return <button onclick="{handleClick}">点击次数:{count}</button>;
}
// 3. 阻止默认行为(如表单提交)
function Form() {const handleSubmit = (e) =&gt; {// 阻止表单默认提交(原生与React写法一致)e.preventDefault();console.log("表单已处理,不刷新页面");};return (<form onSubmit="{handleSubmit}"><button type="submit">提交表单</button></form>);
}

🧠 为什么这些概念如此重要?

理论上,即使不掌握这些概念,你也能 “拼凑” 出一个 React 应用 —— 但代价是:频繁困惑、卡壳,只能从 Stack Overflow(或国内的掘金、CSDN)复制代码,却不懂背后的逻辑。

这些概念是 React 开发的 “地基”:它们不仅帮你写出代码,更能让你理解 “React 为什么要这么设计”(比如 Hooks 依赖闭包、状态不可直接修改)。

🎥 加餐:视频学习资源

如果你偏好 “视觉 + 场景化” 学习,不必局限于国外平台(如 YouTube)。国内的技术平台(如 B 站、掘金视频)有大量优质教程,搜索 “React 前置 JS 知识点”“React 基础 JS 概念”,就能找到适合国内开发者的入门内容,帮你更清晰地建立知识体系。

✨ 最后想说的话

掌握 React,不只是学习一个新库 —— 更是深化 JavaScript 基础的过程。在急于学习 JSX、Hooks 或路由之前,先夯实这些核心概念,你会发现后续的 React 学习会 “顺理成章”,而不是 “死记硬背”。

祝大家编码愉快!🚀

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/915843.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二维下标极大数组(二维 map)

在遇到某些题的时候,我们会遇到下标 \(x,y\) 范围较大(如\(10^6\))但点数较小(比如就 \(10^5\) 个)的情况。如果只有一个 \(x\) 的话我们会选择使用 map 或者 unordered_map 来解决,但是如果是二维,这就有些难办…

PySide6 之自定义弹出框

一、效果图二、示例代码 核心代码class MyBaseDialog(QDialog):def __init__(self, parent = None):super().__init__(parent)self._hBoxLayout = QHBoxLayout(self)# 遮罩层self.windowMask = QWidget(self)self.widg…

实用指南:数学建模--Topsis(Python)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

CF932E Team Work

代数推导天地灭,组合意义保平安。其实啥也不会 将题目转化为,有 \(k\) 个带标号的奶龙,要分给 \(i\) 个带标号的树气,其中这 \(i\) 个树气是从 \(n\) 个树气中选出来的,求总方案数。 首先你考虑到会有很多树气选不…

襄阳市住房和城乡建设局官方网站网站服务器端口如何做防护

Trunc 在oracle中&#xff0c;可利用 trunc函数 查询当天数据&#xff0c;该函数可用于截取时间或者数值&#xff0c;将该函数与 select 语句配合使用可查询时间段数据 查询当天数据 --sysdate是获取系统当前时间函数 --TRUNC函数用于截取时间或者数值&#xff0c;返回指定的…

HTTP3与HTTP2的性能对比

HTTP/3 相对于 HTTP/2 的性能提升是显著的,但其优势并非在所有场景下都立竿见影。核心的差异源于底层传输协议从 TCP 切换到了 QUIC(基于 UDP)。 下面我们从几个关键维度进行详细对比,并总结适用场景。核心差异:T…

KubeSphere 社区版即将发布:开启云原生新篇章

各位社区朋友,大家好。最近 KubeSphere 社区版的消息引发了不少讨论。KubeSphere 社区版即将于国庆后和大家见面。今天,我们想先向大家介绍一下 KubeSphere 社区版。 为什么推出社区版 云原生技术发展至今,Kubernet…

从零开始:c#如何优雅的操作临时文件/数据?以ASP文件下载为例

从零开始:c#如何优雅的操作临时文件/数据?以ASP文件下载为例在程序开发中,我们经常需要处理临时文件,例如:安全替换大文件:先将内容写入临时文件,成功后再替换目标文件,避免写入过程中断导致数据损坏。 进程间数…

KDL - 金山云数据湖系统参数

KDL - 金山云数据湖系统参数 ${flow.name} ${flow.id} ${job.name} ${job.id} ${biz.date} #20250924 ${yyyyMM} #202509

表情网站源码网站里面内外链接如何做

最好的种树是十年前,其次是现在。歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主 放弃很容易但是坚持一定很酷 我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的鼓励 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&…

wordpress搭建个人网站费用wordpress 8080

我们每天都在开发Java,每天都在使用JDK,那么我们了解JDK的发展史吗,这篇文章将带你深入了解JDK的发展史。 JDK(Java Development Kit)是Java开发者工具包,是用于编写Java程序和运行Java程序的软件开发工具集。自从1995年Java语言首次发布以来,JDK已经经历了数十年的发展…

内力网站建设深圳常平网站建设制作公司

哲哲是一位硬核游戏玩家。最近一款名叫《达诺达诺》的新游戏刚刚上市&#xff0c;哲哲自然要快速攻略游戏&#xff0c;守护硬核游戏玩家的一切&#xff01; 为简化模型&#xff0c;我们不妨假设游戏有 N 个剧情点&#xff0c;通过游戏里不同的操作或选择可以从某个剧情点去往另…

大丰网站建设公司鞍山网站制作开发

由于最近比较忙&#xff0c;所以本周搞了一个相对简单的验证码&#xff0c;就是抖音Tiktok的滑块验证码&#xff0c;这也是接到客户的一个需求。这种验证码通常在电脑端登录抖音、巨量引擎的的时候出现。 首先看一下最终的效果&#xff1a; 验证码识别过程 1、利用爬虫采集图…

网上做外贸都有哪些网站做网站要多少

主要是安装一些插件&#xff0c;c/c开发常用的插件有如下几个&#xff1a; 插件名称功能C/CC 和 C的编译环境C/C SnippetsC/C重用代码块C/C Advanced LintC/C静态检测Code Runner代码运行Include AutoComplete自动头文件包含Rainbow Brackets彩虹花括号&#xff0c;有助于阅读…

建设网站建设什么挣钱织梦技术网站模版

0.按照步骤&#xff0c;快速进行python的开发准备工作 1. Python解释器的下载 下载地址 https://www.python.org/ 选择对应你的系统的安装包 2.记得勾选这里将python加入你的路径中 3.有如下四个程序表明安装成功 4.点击上图中的第二个程序打开窗口检查解释器能否正常工作 输…

乌海做网站网站开发服务费入什么科目

我们知道C的类应当是先定义&#xff0c;然后使用。但在处理相对复杂的问题、考虑类的组合时&#xff0c;很可能遇到俩个类相互引用的情况&#xff0c;这种情况称为循环依赖。 例如&#xff1a; class A { public:void f(B b);//以B类对象b为形参的成员函数//这里编译错位&…

房建设计网站excel+表格+做的网站

k8s subPathExpr作用 场景&#xff1a; 对于一个deployment或者job拉起的服务&#xff0c;所有pod都是一样的配置&#xff0c;如果都挂载了宿主机的同一个目录&#xff0c;那么就会互相干扰&#xff0c;我们希望挂载相同目录&#xff0c;且在这个目录下&#xff0c;每个pod建立…

答题互动网页收藏

<!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"&…

常见问题解决 --- windows软件运行报错MSVCP140 ATOMIC WAIT.dI

常见问题解决 --- windows软件运行报错MSVCP140 ATOMIC WAIT.dI解决方法: https://aka.ms/vs/17/release/vc_redist.x64.exe 下载安装即可 其他参考: https://www.dll-files.com/msvcp140_atomic_wait.dll.htmlhttps…

芯脉:面向高速接口的SoC架构与完整性设计<3> - 教程

芯脉:面向高速接口的SoC架构与完整性设计<3> - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&q…