ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

JavaScript核心知识梳理:从变量到异步请求的入门路线

JavaScript核心知识梳理:从变量到异步请求的入门路线 如果你正准备入门前端那么 JavaScript 是你绕不开的一门语言。现在网上讲 JavaScript 的教程很多但大多要么太零散、要么一上来就讲底层概念容易把新手劝退。这篇笔记的定位很简单用一条主线把 JavaScript 最核心的知识点串起来从变量、函数、DOM 操作到接口请求把“能写代码”这个目标放在第一位顺便把学习中最常遇到的问题一起讲清楚。文中会按实际开发顺序来组织内容而不是按文档顺序平铺直叙。每段内容都尽量能被直接用起来代码也都可以复制到浏览器控制台里跑一遍。这篇内容面向两类读者第一类是刚学完 HTML 和 CSS、准备开始接触 JavaScript 的前端新手第二类是已经会用框架、但发现自己原生 JavaScript 基础不够扎实经常在报错和调试上浪费时间的开发者。文中的代码不需要安装任何开发工具只要有一个浏览器就能全部运行。你会学到变量与数据类型、函数与作用域、数组与对象操作、DOM 操作与事件处理、ES6 常用语法、异步编程和接口调用最后还会整理一份 JavaScript 常见报错和排查方法。把这条主线走通以后再去看框架、看源码或者做前端面试题会轻松很多。1. JavaScript 基础核心能力速览学习模块说明运行环境浏览器控制台、HTML 文件、Node.js 均可运行语言版本ES6前后端通用重点掌握变量、函数、数组、对象、DOM、事件、异步、接口请求是否需要安装环境不需要Chrome / Edge 浏览器即可配套资料源码示例、知识点文档、调试技巧适合人群前端入门者、基础薄弱者、准备前端面试者学习路径语法基础 - 浏览器交互 - 异步与接口 - 调试排错有读者可能会问现在都直接用 Vue、React 写项目了还要不要花时间学原生 JavaScript答案是必须学。框架只是封装了 JavaScript底层的事件循环、原型链、数组方法、Promise 机制全都依赖原生语言基础。在实际项目里遇到的很多诡异 bug 最后都能定位到原生 JavaScript 的某个细节上。学 JavaScript 不是“面试前背八股”而是把写代码时真正用得到的工具一件件装进脑子里。2. JavaScript 到底是什么——先搞清边界再动手JavaScript简称 JS是一种运行在浏览器里的脚本语言最初设计目的是让网页具备交互能力。经过多年的发展它已经可以跑在服务器端Node.js、桌面端Electron、移动端小程序 / React Native甚至嵌入式设备上。但对初学者来说最重要的使用场景仍然是在网页中操作 DOM、处理用户事件、向后端发送请求、控制页面内容变化。那 JavaScript 能做什么可以这样概括操作页面元素改变文字、样式、结构。响应用户交互点击、输入、滚动、键盘事件。与服务器通信使用 fetch / axios 发送接口请求。数据存储操作 localStorage、sessionStorage、Cookie。构建完整应用配合框架实现复杂单页应用。JavaScript 做不了什么这里需要提醒一下浏览器里的 JavaScript 不能直接读取本地文件系统除非用户明确授权、不能访问操作系统的底层 API、不能绕过浏览器安全策略直接访问其他域名的接口。这不是“能力不足”而是刻意设计的安全限制。理解了边界你在排查问题时就会更有方向感。还有一个容易被忽略的问题JavaScript 和 Java 没有任何关系。取名时只是借用了 Java 的热度。它们的语法风格有一些相似C 系语法但运行环境、类型系统、生态完全不是一个体系。前端面试里偶尔会问“JavaScript 和 Java 的区别”其实就是考察你是否只是背了名字、没有真正理解语言本身。3. 环境准备——不装 IDE 也能启动的零基础方案开始写 JavaScript 之前不需要下载任何复杂的开发工具。这里给出一套最简单的启动流程。第一步打开 Chrome 或 Edge 浏览器按 F12 打开开发者工具切换到 Console控制台面板。然后输入下面这行代码回车console.log(hello javascript);如果你能在控制台看到输出说明 JavaScript 运行环境已经就绪。这个过程不需要配置环境变量、不需要安装 Node.js、不需要创建工程目录。所有基础语法练习都可以在这里完成。第二步如果你想模拟真实网页开发环境创建一个 HTML 文件把下面的代码粘贴进去用浏览器打开!DOCTYPE html html langzh-CN head meta charsetUTF-8 titleJavaScript 基础测试页/title /head body h1 idtitle点击按钮改变这段文字/h1 button idbtn点我/button script const btn document.getElementById(btn); btn.addEventListener(click, function () { document.getElementById(title).textContent 文字已被 JavaScript 修改; }); /script /body /html这个例子就是最完整的开发闭环HTML 负责结构CSS 负责表现JavaScript 负责行为。不管以后用 Vue、React 还是原生开发底层本质都一样。第三步可选安装 Node.js用于模拟后端运行环境。如果你只想学前端基础暂时可以不装 Node。等学到接口请求、模块化、打包工具时再装也不迟。需要特别提醒的是初学者尽量不要一上来就配置 Vite、Webpack、Babel 这些构建工具。它们解决的问题是“工程化”不是“写代码”。在基础语法没熟悉之前工具链只会分散你的注意力让你花大量时间处理环境问题而不是学语言本身。4. 变量、数据类型与作用域——写出可读的代码JavaScript 的变量声明有三种方式var、let、const。它们的区别是前端面试题里最高频的基础考点。var a 1; // 老语法函数作用域存在变量提升 let b 2; // ES6 语法块级作用域可以重新赋值 const c 3; // ES6 语法块级作用域声明后不能重新赋值实际开发中的推荐做法是优先使用 const只有在确认变量需要重新赋值时才用 let尽量不要用 var。这样做的好处是代码意图清晰也减少了作用域污染和意外赋值的问题。JavaScript 的数据类型可以分为两大类原始类型string、number、boolean、null、undefined、symbol、bigint。引用类型object包含数组、函数、日期、正则等。这里有一个高频踩坑点typeof null 的结果是 object。这是 JavaScript 早期设计遗留的 bug但官方决定永远不修复。面试会问开发时也容易遇到建议直接记住结论。再看作用域。JavaScript 采用词法作用域也就是说函数的作用域在定义时就已经确定而不是在调用时确定。下面这个例子能帮你快速理解const name 张三; function outer() { const name 李四; function inner() { console.log(name); // 输出 李四 } inner(); } outer();inner 函数定义在 outer 函数内部所以它会先去自己的局部作用域找 name找不到再去外层作用域找。这就是“作用域链”的基本行为。理解作用域是理解闭包、变量提升、this 指向等进阶概念的前提。5. 运算符、流程控制与函数——把逻辑清晰表达出来JavaScript 的运算符和大多数编程语言类似这里重点讲几个容易出错的点。相等比较运算符是第一个坑。JavaScript 有两组相等运算符 和 。 会做隐式类型转换所以1 1的结果是 true。而 会先比较类型类型不同直接返回 false所以1 1的结果是 false。实际开发中一律使用 这也是行业规范要求的。逻辑运算符需要掌握短路求值的用法// 短路求值前面为 true直接取后面的值 const result true 有值; // 有值 // 默认值写法 const params userInput || 默认参数; // 可选链写法ES2020 const city userInfo?.address?.city || 未知城市;短路求值在真实项目里非常常见可以显著减少 if 嵌套。流程控制建议掌握三种if/else、switch、循环。这里重点提醒一点for 循环配合数组时尽量用 for...of 而不是 for...in因为 for...in 遍历的是对象的键名且有原型链污染风险数组遍历更推荐用 forEach、map、filter 等方法后面会有专门小节。函数是 JavaScript 的核心。函数声明、函数表达式、箭头函数是三种常见写法// 函数声明 function add(a, b) { return a b; } // 函数表达式 const add2 function (a, b) { return a b; }; // 箭头函数 const add3 (a, b) a b;函数声明存在变量提升可以先调用后声明函数表达式和箭头函数不行。这里的表现差异在面试和代码调试中经常出现。箭头函数还有两个特点没有自己的 arguments 对象不绑定自己的 this。后者在事件回调、定时器回调中有很重要的作用。从实际开发经验看前端的函数命名应该尽量用“动词 名词”的格式例如 getUserList、checkInput、updateCount。这能让代码可读性提升一个档次。6. 数组与字符串——高频操作用法详解这一部分在 JavaScript 中的使用频率极高值得详细展开。数组的常用方法比较多建议按“行为类别”来记新增/删除push、pop、shift、unshift、splice查找indexOf、find、findIndex、includes遍历forEach、map、filter、some、every、reduce排序sort、reverse截取/拼接slice、concat、join新结构Array.from、解构赋值、展开运算符新手比较容易混淆的是 slice 和 splice。slice 是“截取”返回新数组不修改原数组splice 是“删除/替换”直接修改原数组。看下面的对比const arr1 [1, 2, 3, 4, 5]; const newArr arr1.slice(1, 3); // [2, 3] const arr2 [1, 2, 3, 4, 5]; const removed arr2.splice(1, 2, 99); // 删除下标1开始的两个元素替换为99 // arr2 变成 [1, 99, 4, 5]removed 是 [2, 3]建议在没有把握是否修改原数组时先查一下文档或者先在控制台验证一次。这个习惯能帮你减少很多隐蔽 bug。map 和 forEach 的区别也非常关键map 返回一个新数组forEach 只做遍历不返回结果。初学者容易把 map 当 forEach 用最后发现数据没变化。const numbers [1, 2, 3, 4]; const doubled numbers.map(num num * 2); // [2, 4, 6, 8] numbers.forEach(num { console.log(num * 2); // 只打印不返回新数组 });字符串方法同样需要熟练掌握length、charAt、startsWith、endsWith、includes、indexOf、slice、substring、toUpperCase、toLowerCase、trim、split、replace、replaceAll。这里说一个高频场景——去掉字符串首尾空格并用逗号拆分成数组const str apple, banana , orange ; const cleaned str.trim().split(,).map(item item.trim()); // [apple, banana, orange]字符串是不可变的。任何字符串方法都不会修改原字符串只会返回新字符串。这是和数组方法最大的区别。当你发现字符串操作后原变量没变时不要怀疑是 bug这是语言设计的结果。7. 对象操作与解构赋值——接口数据处理的核心前端的很大一部分工作是把后端接口返回的数据转换成页面需要的结构。这个过程几乎离不开对象和数组的配合操作。创建对象最常用的是对象字面量const user { name: 王五, age: 25, hobbies: [coding, reading], address: { city: 北京, district: 海淀区 } };读取属性可以通过点语法或括号语法。当属性名是动态变量时必须用括号语法const key name; console.log(user[key]); // 王五解构赋值是 ES6 的重要特性。它可以从对象或数组中提取值并赋给变量尤其在处理接口返回数据时非常方便// 对象解构 const { name, age } user; console.log(name, age); // 数组解构 const colors [red, green, blue]; const [firstColor, secondColor] colors; // 解构时重命名 const { name: userName } user; console.log(userName); // 解构并设置默认值 const { role 普通用户 } user;还有一个非常实用的知识深拷贝与浅拷贝。浅拷贝直接使用展开运算符或 Object.assign但这里要注意——展开运算符只做一层浅拷贝如果对象里有嵌套对象修改拷贝后的嵌套对象会影响到原对象。const userCopy { ...user }; userCopy.address.city 上海; console.log(user.address.city); // 上海因为 address 是引用类型如果需要深拷贝可以考虑结构化克隆方法。在浏览器环境里最简单的深拷贝方式是使用 structuredCloneconst deepCopy structuredClone(user); deepCopy.address.city 上海; console.log(user.address.city); // 北京不过在 Node.js 老版本或某些特殊环境里 structuredClone 不可用所以做通用方案时要确认运行环境。也可以用 JSON.parse(JSON.stringify(obj)) 实现“轻量深拷贝”但此方式会丢失 undefined、函数、Symbol 等类型适合纯数据对象。8. DOM 操作与事件处理——做会动的页面DOM 全称 Document Object Model是 JavaScript 操作网页结构的接口。浏览器会把 HTML 解析成一个树形结构JavaScript 可以在这个树上进行查找、新增、修改、删除操作。页面元素查找的常用 API 有document.getElementById(id); document.querySelector(.class); document.querySelectorAll(div.item); document.getElementByTagName(div);推荐优先使用 querySelector 和 querySelectorAll它们支持完整的 CSS 选择器语法写法灵活。需要注意 querySelectorAll 返回的是 NodeList不是数组如果需要使用 map 等数组方法要先转换const items document.querySelectorAll(li); const textList Array.from(items).map(item item.textContent);修改内容是 DOM 操作中最常见的需求。修改文本用 textContent修改 HTML 结构用 innerHTML修改样式用 styleconst title document.getElementById(title); // 修改文本 title.textContent 新的标题; // 修改样式 title.style.color red; title.style.fontSize 20px; // 添加 class title.classList.add(active); // 切换 class title.classList.toggle(hidden);事件处理是让页面响应用户操作的核心机制。最常用的绑定方式是 addEventListenerconst button document.getElementById(btn); button.addEventListener(click, function (event) { console.log(按钮被点击了); console.log(event.target); // 触发事件的元素 });常见事件类型包括 click、dblclick、input、change、submit、keydown、keyup、scroll、mouseover、mouseout 等。当页面结构比较复杂时你需要了解“事件冒泡”和“事件委托”这两个概念。事件从最内层元素向外层传播的过程叫作冒泡。利用冒泡机制可以把监听器挂到父元素上统一处理子元素的事件这就是事件委托const list document.getElementById(list); list.addEventListener(click, function (event) { if (event.target.tagName LI) { console.log(点击了列表项, event.target.textContent); } });这种写法可以显著减少事件监听器的数量尤其适合动态增加元素的列表场景。动态创建的 DOM 元素不需要额外绑定事件父元素统一处理即可。9. ES6 常用语法——让代码更简洁的关键ES6ECMAScript 2015是一次革命性的版本更新。现在的开发基本上都基于 ES6 语法这里挑最常用的几个知识点展开。模板字符串是写字符串时最好用的语法之一。它使用反引号包裹支持变量插值也支持多行文本const name 李雷; const age 18; // 旧写法 const str1 我叫 name 今年 age 岁; // 新写法 const str2 我叫${name}今年${age}岁;展开运算符用三个点表示可以用来展开数组、拼接数组、展开对象、代替 apply 调用函数等const arr1 [1, 2, 3]; const arr2 [4, 5, 6]; const combined [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6] const obj1 { a: 1, b: 2 }; const obj2 { c: 3 }; const merged { ...obj1, ...obj2 }; // { a: 1, b: 2, c: 3 }模块化是 ES6 最核心的工程能力。一个 JavaScript 文件可以通过 export 导出内容通过 import 导入其他文件的内容// 导出写法 export const baseURL https://api.example.com; export function request(url) { return fetch(url); } // 导入写法 import { baseURL, request } from ./api.js;默认导出和具名导出是两种不同的方式。具名导出用花括号导入默认导出则不需要花括号// config.js export default { timeout: 5000, retry: 3 }; // 使用 import config from ./config.js; console.log(config.timeout);最后还有一个高频考点Map 和 Set。Map 是一种键值对集合和对象的主要区别是 Map 的键可以是任意类型而且 Map 有更好的遍历顺序。Set 是一种类似数组的结构但成员的值都是唯一的经常用来去重// Set 去重 const arr [1, 2, 2, 3, 3, 4]; const uniqueArr [...new Set(arr)]; // [1, 2, 3, 4] // Map 的基本使用 const userMap new Map(); userMap.set(user1, { name: 张三 }); userMap.get(user1); userMap.has(user1);10. 异步编程与接口请求——从回调到 async/await异步编程是 JavaScript 学习曲线最陡的地方也是前端开发真正走向实战的关卡。JavaScript 是单线程语言它通过事件循环机制执行代码。当一个异步操作发起时比如发送网络请求它不会阻塞后续代码而是等结果返回后通过回调函数继续执行。最容易理解的异步方案是回调函数但回调嵌套过多会形成“回调地狱”。因此现代开发中优先使用 Promise 和 async/await。先看 Promise 的基本结构const fetchData () { return new Promise((resolve, reject) { setTimeout(() { const success true; if (success) { resolve(数据加载成功); } else { reject(数据加载失败); } }, 1000); }); }; fetchData() .then(data { console.log(data); }) .catch(err { console.error(err); });Promise 有三个状态pending进行中、fulfilled已成功、rejected已失败。状态一旦从 pending 变为 fulfilled 或 rejected就不能再变化。async/await 是 Promise 的语法糖它让异步代码看起来像同步代码可读性会好很多async function loadData() { try { const data await fetchData(); console.log(data); } catch (err) { console.error(请求失败, err); } }注意 await 只能在 async 函数中使用。如果在普通函数里直接写 await浏览器会直接抛错。在真实项目中最常见的异步场景就是调用后端接口。原生浏览器提供了一个 fetch API可以发送网络请求async function getUserProfile(userId) { try { const response await fetch(/api/users/${userId}); if (!response.ok) { throw new Error(接口错误${response.status}); } const data await response.json(); console.log(data); return data; } catch (err) { console.error(接口请求失败, err); } } // 调用 getUserProfile(1001);fetch 返回的是一个 Response 对象需要调用 response.json() 或 response.text() 来获取具体数据。建议每次调用接口都检查 response.ok否则当后端返回 404 或 500 时虽然 HTTP 请求已经完成但 fetch 不会自动进入 catch。并行请求是另一个高频场景。如果多个接口之间没有依赖关系应该使用 Promise.all 并行请求而不是依次等待async function loadPageData() { const [userInfo, productList, notices] await Promise.all([ fetch(/api/user).then(res res.json()), fetch(/api/products).then(res res.json()), fetch(/api/notices).then(res res.json()) ]); console.log(userInfo, productList, notices); }接口请求还会遇到超时、错误重试、loading 状态控制等问题。建议把它封装成统一的请求工具函数方便在页面中复用出了问题也只需要改一处地方。11. 前端 JavaScript 常见报错与排查方法这一部分直接从实际报错出发把最常见的错误提示和排查思路整理成表。报错提示常见原因排查方式Cannot read properties of undefined尝试读取 undefined 的属性检查数据是否为空、接口返回是否正确xxx is not a function变量不是函数却被调用检查函数名是否写错、是否被重新赋值undefined is not iterable对 undefined 使用展开或 for...of确认目标是否为可迭代对象Uncaught SyntaxError: Unexpected token语法错误查看报错位置检查括号、引号、逗号ReferenceError: xxx is not defined变量未声明或作用域不对检查变量声明位置和拼写TypeError: Cannot read properties of null未找到 DOM 元素检查 DOM 不存在时是否提前执行了 JSPromise 状态为 rejected 且未处理没有 catch Promise 错误在 async 函数内使用 try/catch这里专门回答一个搜索量很高的问题javascript:void(0) 是什么很多初学者在老代码里会看到hrefjavascript:void(0)这种写法。它的作用是让a标签点击后不跳转、页面不刷新同时执行 JavaScript 代码。现在的开发并不推荐这种写法因为浏览器和搜索引擎对这个语法的处理方式存在兼容问题更好的做法是使用 button 元素或在事件处理函数里调用 preventDefault。另一种高频问题是“为什么我不能用 getElementById 获取到元素”。这通常是因为脚本放在 HTML 文件的head中而脚本执行时 DOM 还没有解析完成。解决方法有三种把 script 放在 body 末尾使用 DOMContentLoaded 事件使用 window.onload。推荐使用 DOMContentLoaded因为它不需要等待图片等资源加载完成document.addEventListener(DOMContentLoaded, function () { const title document.getElementById(title); console.log(title); });接口返回的数据渲染不出来也是新手经常踩的坑。常见的表现是页面空白看控制台发现 data 是 undefined 或者 data.list 为 undefined。出现这种情况首先打印接口返回的完整数据查看层级结构是否和代码里的路径一致。后端返回的字段名可能和前端代码里的字段名不一致这是字段名拼写问题不是数据处理问题。12. 前端开发最佳实践与学习建议基础语法掌握之后更重要的是养成正确的编码习惯。JavaScript 这门语言的自由度比较高同样一个功能可以有几十种写法但如果代码没有可维护性它很快就会成为技术债。下面给出几条工程化的建议。第一变量声明时先想清楚它是否会被重新赋值。默认使用 const只有确认需要重新赋值时才使用 let。这个习惯看起来琐碎但能避免很多隐蔽作用域问题。第二尽量不要裸用 var。var 会带来变量提升和函数作用域相关的各种意料之外的行为。新代码里用 let 和 const已经是整个前端行业的基本共识。第三写函数时保持短小一个函数只做一件事。如果一个函数超过 50 行建议考虑拆分。如果函数里出现三层以上的嵌套基本都是需要重构的信号。第四所有接口请求都要做错误处理。不要只是 console.log 一下至少要在界面给出用户可理解的错误提示。请求超时、接口 500、数据格式变化这些都会真实发生错误处理不写线上就容易出事故。第五学习时多用浏览器控制台验证。遇到不确定的语法第一反应不是去搜“xxx 报错”而是在控制系统里把代码跑一遍。很多疑问通过一次实际输出就能解决。这里说一个常用的小技巧使用 console.table 输出数组/对象数据比 console.log 更适合查看多个对象的结构const users [ { id: 1, name: 张三 }, { id: 2, name: 李四 } ]; console.table(users);控制台会以表格形式展示数据字段结构一目了然排查接口字段非常方便。13. 调试思路与源码学习方法遇到 JavaScript bug正确的调试顺序比盲目修改重要得多。建议按照“复现 - 定位 - 修改 - 验证”的闭环来操作。复现阶段先确认错误是否每次都能出现。如果只是偶尔出现先排查是否跟时间、网络、用户操作路径有关。定位阶段打开控制台看报错信息、堆栈和数据打印结果必要时在可疑代码处加 console.log。修改阶段一次只改一处改完立刻测试。验证阶段不仅要验证当前场景还要考虑边界输入比如空数据、超长文本、网络断开。很多前端学习者到了某个水平后开始想看框架源码。这里提醒一下看源码不要从头看到尾而是带着问题看。比如你想知道这个工具函数为什么这样写就在源码里搜索这个函数名只看它被调用和实现的局部上下文。先从自己用的 API 入手再逐步扩大阅读范围这样效率会高很多。直接通读源码很容易迷失在细节中。另外在开发过程中遇到报错时可以先去搜索引擎查报错信息然后确认运行环境最后动手验证。不要每次报错都依赖别人学会阅读文档和报错信息是前端工程师最核心的能力之一。14. 下一步该学什么如果你把前面几个章节的代码都跑通了说明 JavaScript 基础部分已经基本过关。接下来可以按顺序做下面几件事。第一结合 HTML 和 CSS 做几个完整页面。比如做一个待办清单页面涉及 DOM 增删、事件绑定、数组操作、本地存储。这个小项目能把这些知识点全部串起来。完成后你可以尝试加上搜索、排序、筛选功能。第二学习 axios 和 fetch 的真实项目用法。写一个小工具页从公开接口或自己的本地服务拉取数据渲染到页面上。这样你会真正理解接口请求、异步渲染和 loading 状态之间的关系。第三学习模块化和打包工具的基本用法。原生的 JavaScript 文件直接引入一个项目会越来越复杂这时再引入 Vite 或 Webpack 才是合理的顺序。先用 Vite 创建一个小项目把之前写的模块拆分成独立文件。第四学习常见框架之一。Vue 和 React 二选一即可不要同时学两个。框架能帮你提高开发效率但不要跳过原生基础。前端面试题里经常出现的手写 Promise、防抖节流、数组去重、深拷贝本质上都是原生 JavaScript 基础上的知识延伸。关于时间安排说明一下标题里的“2 小时快速入门”只是一种学习节奏的提法。实际掌握 JavaScript 需要分阶段练习第一遍先快速过语法第二遍再带着问题深入。速度固然重要但把每个案例亲手写过一遍更重要。阅读代码和亲手写出代码在大脑里产生的记忆效果完全不同。建议把这篇文章收藏备用。后面遇到变量作用域、数组方法、DOM 事件、异步请求、接口调试相关的问题时可以直接回查对应章节。真正的掌握不是看一遍就结束而是遇到 bug 时能快速定位、修复并在下一次写出更稳的代码。
返回列表