JavaScript核心语法速成笔记:从变量到Promise,30分钟构建前端基础
发布时间:2026/9/8 20:32:03来源:尧图网络
各位前端新手朋友们大家好相信你在开始学习前端的路上一定无数次听过“JavaScript”这个名字。它和 HTML、CSS 并称为前端开发“三剑客”是让网页“活”起来的关键。很多初学者在看完一堆概念后依然写不出效果或者看到网上零散的知识点不知道从哪下手。今天这篇文章就用 30 分钟的时间帮你把 JS 最核心的语法体系串起来从变量、数据类型、函数到数组字符串操作再到进阶的 Promise 和模块化全部覆盖还附带完整的实战案例和常见报错排查思路。不管你是完全零基础还是学过一点但知识不成体系这篇速成笔记都非常适合你。1. 核心概念JavaScript 到底是什么为什么必学1.1 从“会动”的网页说起咱们先抛开术语用大白话理解一个网页的构成。HTML 负责搭建页面的结构和内容比如标题、按钮、图片CSS 负责美化让页面变得好看比如颜色、大小、间距。但是如果你点击一个按钮它没有任何反应页面内容不会动态更新那它就只是一个“静态相册”。JavaScript 的出现就是为了解决这个问题。它可以让页面“动”起来点击按钮弹出提示框、下拉菜单展开收起、数据实时刷新、表单提交前校验、和服务器交互获取数据……这些都是 JS 的功劳。用专业一点的话来说JavaScript简称 JS是一种轻量级的、解释型的、基于原型的编程语言。它最早被设计出来用于浏览器端让网页具备交互能力。如今随着 Node.js 的出现JS 已经可以运行在服务器端成为全栈开发的重要一环。1.2 JS 和 Java、C 这类语言有什么区别第一次接触编程的同学可能好奇为什么 JS 的入门门槛看起来比 Java、C 低很多解释执行JS 代码不需要提前编译成二进制文件而是由浏览器或 Node.js边解释边执行。写完之后刷新页面就能看到效果。弱类型/动态类型声明变量时不需要指定类型同一个变量可以存数字、字符串、布尔值。这带来便利的同时也要求写代码时更自律否则容易出现“类型意外”的 bug。基于原型JS 的继承机制是通过“原型链”实现的而不是传统面向对象语言的“类继承”。当然ES6 之后引入了 class 语法糖降低了理解门槛。1.3 常见应用场景浏览器端交互开发表单验证、轮播图、Tab 切换、瀑布流加载等。前端框架开发Vue、React、Angular 的底层都是 JS或 TypeScript。服务端开发Node.js Express/Koa可以用 JS 写后端接口。桌面应用Electron 框架让 JS 可以开发跨平台桌面软件。小程序开发微信小程序、uni-app 等也离不开 JS 语法基础。所以无论你以后想走纯前端、全栈还是跨端开发JS 都是绕不开的第一道门。这也是为什么前端面试题、前端八股文里JS 核心语法永远是重中之重。2. 环境准备在哪儿运行你的第一段 JS 代码既然要动手学第一步就是把“写代码”和“看结果”的工具准备好。好消息是学习 JS 核心语法几乎不需要安装重型软件。2.1 方式一浏览器控制台最简单每个现代浏览器都自带开发者工具DevTools。以 Chrome 为例按下键盘上的F12键或者右键点击页面任意位置选择“检查”然后点击Console控制台选项卡就能在下方输入 JS 代码了。// 在 Console 中输入以下内容并回车 console.log(Hello, JavaScript!);浏览器会立刻输出这行文本。Console 是 JS 初学阶段使用频率最高的“草稿纸”方便你验证一行代码的执行结果。2.2 方式二HTML 文件中的 script 标签接近实际开发实际开发中JS 代码通常会嵌入到 HTML 页面中或者单独放在 .js 文件里再引入。我们可以在本地新建一个 HTML 文件用记事本或任意编辑器写好代码双击用浏览器打开。!DOCTYPE html html langzh-CN head meta charsetUTF-8 titleJS 快速体验/title /head body h1 idtitle点击按钮改变这段文字/h1 button idbtn点我/button script // 这段 JS 代码会在页面加载时执行 document.getElementById(btn).addEventListener(click, function () { document.getElementById(title).innerText 你已经学会了 JS 基础事件; }); /script /body /html这里先不深究每一行的意思等你学到“事件”和“DOM 操作”之后再回来看会发现非常简单。2.3 方式三在 Node.js 环境中运行进阶如果你已经安装了 Node.js可以打开终端命令行输入node命令进入交互模式输入代码后回车执行也可以写一个test.js文件然后用node test.js运行。node test.js两种方式都可以。“版本需要根据你的项目实际情况调整本文示例以常见环境为例重点演示配置思路。”大部分核心语法都不依赖特定版本不过我还是建议你用较新的稳定版浏览器或 Node.js因为会支持更多 ES6 新语法。3. 核心语法拆解变量、类型与操作符3.1 变量声明let、const、var 怎么选变量是存储数据的容器。JS 中声明变量常见的关键字有三个var、let、const。varES6 之前的旧写法。存在“变量提升”和函数作用域的问题容易出现意外结果。letES6 引入的块级作用域变量推荐使用。constES6 引入的块级作用域常量声明后不能再重新赋值推荐优先使用。// 用 const 声明一个常量值不可更改 const userName 张三; // userName 李四; // 这里会报错Assignment to constant variable. // 用 let 声明一个变量值可以更改 let age 20; age 21; console.log(age); // 输出 21 // var 在现在开发中不建议优先使用 var oldWay 不推荐;块级作用域理解if (true) { let blockVar 我只能在 if 的 {} 里使用; var notBlockVar 我可以泄漏到外面; } // console.log(blockVar); // 报错blockVar is not defined console.log(notBlockVar); // 正常输出这里需要注意的是const声明对象时它限制的是“绑定关系”而不是“内部内容”。也就是说const obj {}之后你可以修改obj.name x但不能再执行obj {}。3.2 数据类型七种基础类型 引用类型JS 的数据类型可以分为两大类。原始类型基本类型number数值整数和小数都算。string字符串用单引号、双引号或反引号包裹。boolean布尔值只有true和false。undefined声明了但没有赋值。null表示“空值”通常由开发者主动设置。symbolES6 新增表示独一无二的值。bigint较新特性用于表示超出 Number 安全范围的整数。引用类型最常见的是object包含普通对象、数组、函数等。let num 42; // number let price 3.14; // number let name 张三; // string let isOk true; // boolean let a; // undefined let b null; // object历史遗留问题null 会被 typeof 检测为 object let obj { name: 李四 }; // object let arr [1, 2, 3]; // object本质上是数组对象 function fn() {} // function判断类型最常用的是typeof操作符。console.log(typeof abc); // string console.log(typeof 123); // number console.log(typeof true); // boolean console.log(typeof undefined); // undefined console.log(typeof null); // object console.log(typeof []); // object需要注意typeof null返回object是一个历史遗留问题并不是说 null 真的是对象。如果要判断一个值是不是数组可以用Array.isArray()或Object.prototype.toString.call()。3.3 运算符算数、比较、逻辑与“隐形坑”算术运算符、-、*、/、%取余、**幂运算ES7。console.log(10 % 3); // 110 除以 3 余 1 console.log(2 ** 3); // 82 的 3 次方比较运算符、、、、、、!、!。这里有一个高频面试考点和的区别。会做“类型转换”后再比较。要求“类型和值都相等”才返回 true。console.log(1 1); // true因为 1 被转成了数字 1 console.log(1 1); // false因为一个是 number一个是 string在工程实践中强烈推荐使用避免因为隐式类型转换带来难以排查的 bug。逻辑运算符与、||或、!非。let x true; let y false; console.log(x y); // false console.log(x || y); // true console.log(!x); // false短路逻辑在业务中经常用到let username ; username || console.log(用户名为空); // 输出“用户名为空”自增与自减i和i的区别是最容易绕晕的一点。let i 1; console.log(i); // 输出 1先取 i 的值再自增 console.log(i); // 输出 2 let j 1; console.log(j); // 输出 2先自增再取值4. 流程控制条件与循环4.1 if/else 条件判断let score 76; let level; if (score 90) { level 优秀; } else if (score 60) { level 合格; } else { level 不合格; } console.log(level); // 合格三元运算符适合简单条件的简写let isAdult age 18 ? 成年人 : 未成年人;4.2 switch 语句当条件分支非常多时switch可能比一连串else if更清晰。注意每个分支末尾的break否则会“穿透”执行下一个分支。let day 5; let dayName; switch (day) { case 1: dayName 星期一; break; case 2: dayName 星期二; break; case 5: dayName 星期五; break; default: dayName 其他; } console.log(dayName); // 星期五4.3 循环for、while、forEachfor 循环当你知道循环次数时最常用。// 输出 0 到 4 for (let i 0; i 5; i) { console.log(i); }while 循环适合不确定循环次数、但知道结束条件的场景。let count 0; while (count 3) { console.log(当前 count , count); count; }for...of 遍历数组ES6let colors [red, green, blue]; for (let color of colors) { console.log(color); }数组的 forEach 方法提供了更函数式的写法。colors.forEach(function (color, index) { console.log(index, color); });5. 函数复用逻辑的核心单元5.1 函数声明与函数表达式函数是一段可以被反复调用的代码块。你可以把它想象成一个“加工机器”传入原材料参数机器内部处理输出产品返回值。// 函数声明 function add(a, b) { return a b; } // 函数表达式 const subtract function (a, b) { return a - b; }; console.log(add(3, 4)); // 7 console.log(subtract(10, 4)); // 6注意函数声明会被“提升”所以可以在声明之前调用函数表达式则不会。5.2 箭头函数ES6箭头函数是现在最流行的写法语法更简洁并且不绑定自己的this。// 传统写法 const double1 function (n) { return n * 2; }; // 箭头函数简写 const double2 (n) n * 2; console.log(double2(5)); // 10如果只有一个参数可以省略圆括号如果函数体只有一行返回值可以省略return和大括号。const square n n * n; console.log(square(4)); // 165.3 参数默认值与 rest 参数参数默认值当调用方没有传参时使用默认值。function greet(name 陌生人) { console.log(你好 name); } greet(小明); // 你好小明 greet(); // 你好陌生人rest 参数把多个参数收集成一个数组适合不确定参数个数的场景。function sum(...numbers) { let total 0; for (let n of numbers) { total n; } return total; } console.log(sum(1, 2, 3, 4)); // 105.4 作用域与闭包“作用域”决定了变量在哪里能被访问到。全局作用域里的变量到处都能访问函数作用域里的变量只能在函数内部访问。“闭包”是一个稍进阶的概念函数内部再返回一个函数并且内部函数可以访问外部函数的变量即使外部函数已经执行完毕。function createCounter() { let count 0; return function () { count; console.log(count); }; } const counter createCounter(); counter(); // 1 counter(); // 2 counter(); // 3这里的count变量被“闭包”保存了下来没有被销毁。前端中常见的节流、防抖、模块化封装都用到了闭包思想。6. 最常用的内置对象与 API字符串、数组、对象6.1 字符串方法与常见业务场景字符串在前端开发里太常用了。这里挑几个最高频的方法。判断字符串是否包含某个内容let str Hello, JavaScript!; console.log(str.includes(JavaScript)); // true console.log(str.includes(Python)); // false这个方法对应了很多前端面试题里的“JS判断字符串是否包含”。也可以使用indexOfconsole.log(str.indexOf(Java)); // 7返回第一次出现的索引找不到返回 -1截取字符串let email userexample.com; let domain email.slice(email.indexOf() 1); console.log(domain); // example.com替换字符串let text 我喜欢小猫; let newText text.replace(小猫, 小狗); console.log(newText); // 我喜欢小狗保留两位小数处理价格时经常用到toFixed(2)。let price 19.9; console.log(price.toFixed(2)); // 19.90注意返回的是字符串 console.log(parseFloat(price.toFixed(2))); // 19.9如果想保留数字类型可以转回浮点数模板字符串ES6是拼接字符串的更优雅方式let username 张三; let age 18; console.log(我叫${username}今年${age}岁);6.2 数组方法map、filter、reduce数组是 JS 中最常用的数据结构之一。除了前面提到的forEach还有几个高频方法。map对数组每个元素依次做处理返回一个新数组。let nums [1, 2, 3, 4]; let squared nums.map(n n * n); console.log(squared); // [1, 4, 9, 16]filter筛选出满足条件的元素返回新数组。let nums2 [10, 23, 35, 40, 52]; let result nums2.filter(n n 30); console.log(result); // [35, 40, 52]reduce把整个数组合并成一个值比如求和。let total nums.reduce((acc, cur) acc cur, 0); console.log(total); // 10find / findIndex查找第一个满足条件的元素或索引。let users [ { id: 1, name: 张三 }, { id: 2, name: 李四 } ]; let user users.find(u u.id 2); console.log(user); // { id: 2, name: 李四 }注意map、filter都不会修改原数组而是返回新数组这符合函数式编程思想也避免了很多潜在副作用。6.3 对象操作与解构赋值对象用{}表示由键值对组成。let person { name: 王五, age: 25, address: { city: 北京, street: xx街 } }; // 访问属性 console.log(person.name); // 王五 console.log(person[age]); // 25 console.log(person.address.city); // 北京 // 修改属性 person.age 26;解构赋值能帮你快速从对象或数组中取数据非常实用。const { name, age } person; console.log(name, age); // 王五 26 const [first, second] [100, 200]; console.log(first, second); // 100 200解构也支持重命名和默认值const { name: userName2, gender 未知 } person; console.log(userName2); // 王五 console.log(gender); // 未知因为 person 中没有 gender 属性6.4 JSON 字符串和对象的互转前端与后端接口交互时数据通常是 JSON 字符串格式。两个方法最常用let obj { name: 张三, age: 20 }; let jsonStr JSON.stringify(obj); console.log(jsonStr); // {name:张三,age:20} let obj2 JSON.parse(jsonStr); console.log(obj2.name); // 张三7. 异步编程Promise 与 async/await7.1 同步和异步前面我们写的代码都是“同步执行”的从上到下一行一行执行前一行完成再执行下一行。但真实开发中经常需要请求网络数据、读取文件、操作数据库这些操作不能阻塞页面否则用户操作时会卡住。这时候就需要“异步”。7.2 回调函数与回调地狱最早的异步写法是回调函数setTimeout(() { console.log(3 秒后执行); }, 3000);逻辑一复杂“回调地狱”就出现了一个回调嵌套一个回调代码很难维护。7.3 Promise 解决链式问题Promise 是 ES6 引入的异步编程解决方案。它有三种状态pending进行中、fulfilled已成功、rejected已失败。状态一旦改变就不会再变。const promise new Promise((resolve, reject) { let success true; setTimeout(() { if (success) { resolve(操作成功); } else { reject(操作失败); } }, 1000); }); promise .then(res { console.log(res); // 操作成功 }) .catch(err { console.log(err); });Promise.all是热点词里出现过的常见考点用于并行执行多个异步任务const promise1 new Promise(resolve setTimeout(() resolve(A), 1000)); const promise2 new Promise(resolve setTimeout(() resolve(B), 2000)); Promise.all([promise1, promise2]).then(results { console.log(results); // [A, B] });Promise.all的特点是“全部成功才算成功有一个失败就整体失败”。如果你希望“谁先返回就先处理谁”可以用Promise.race。7.4 async/await 让异步代码像同步async和await是 ES8 的语法糖极大简化了 Promise 的链式写法。function wait(ms) { return new Promise(resolve setTimeout(resolve, ms)); } async function run() { console.log(开始); await wait(1000); console.log(1 秒后); await wait(2000); console.log(再等 2 秒后); } run();用await时需要小心await只能用在async函数里如果要捕获错误通常配合try...catchasync function loadData() { try { let res await fetch(/api/data); let data await res.json(); console.log(data); } catch (error) { console.error(请求失败, error); } }8. 实战案例完成一个用户信息管理小工具前面讲了这么多零散知识点现在把核心语法串起来做一个项目实战案例一个纯 JS 的用户信息管理小工具实现“添加用户”“筛选成年人”“计算平均年龄”“按姓名搜索”等功能。8.1 需求拆分用一个数组保存用户列表。添加用户输入姓名和年龄放入数组。展示列表把数组渲染成一个字符串输出。筛选成年人返回年龄 18 的用户。计算平均年龄用 reduce 求和再除以长度。按姓名搜索用 includes 做模糊搜索。8.2 完整代码可以直接在浏览器的 Console 中运行下面代码也可以保存为userManager.js并用 Node.js 运行。// 用户管理工具 // 初始用户数据 const users [ { id: 1, name: 张三, age: 20 }, { id: 2, name: 李四, age: 16 }, { id: 3, name: 王五, age: 24 } ]; // 自动生成下一个 id function getNextId() { const ids users.map(user user.id); return ids.length 0 ? Math.max(...ids) 1 : 1; } // 添加用户 function addUser(name, age) { if (!name || typeof age ! number || age 0) { console.error(参数不合法请检查姓名或年龄); return; } const newUser { id: getNextId(), name: name, age: age }; users.push(newUser); console.log(成功添加用户${name}当前共有 ${users.length} 人); } // 展示用户列表 function showUsers() { console.log( 用户列表 ); users.forEach(user { console.log(ID: ${user.id}姓名: ${user.name}年龄: ${user.age}岁); }); console.log(); } // 筛选成年人 function getAdults() { return users.filter(user user.age 18); } // 计算平均年龄 function getAverageAge() { const total users.reduce((sum, user) sum user.age, 0); return (total / users.length).toFixed(1); } // 按姓名搜索模糊搜索 function searchUser(keyword) { return users.filter(user user.name.includes(keyword)); } // 演示 showUsers(); addUser(赵六, 30); addUser(小红, 8); showUsers(); console.log(成年人列表, getAdults()); console.log(平均年龄, getAverageAge()); console.log(搜索张, searchUser(张));8.3 预期输出 用户列表 ID: 1姓名: 张三年龄: 20岁 ID: 2姓名: 李四年龄: 16岁 ID: 3姓名: 王五年龄: 24岁 成功添加用户赵六当前共有 4 人 成功添加用户小红当前共有 5 人 用户列表 ID: 1姓名: 张三年龄: 20岁 ID: 2姓名: 李四年龄: 16岁 ID: 3姓名: 王五年龄: 24岁 ID: 4姓名: 赵六年龄: 30岁 ID: 5姓名: 小红年龄: 8岁 成年人列表 [ { id: 1, name: 张三, age: 20 }, { id: 3, name: 王五, age: 24 }, { id: 4, name: 赵六, age: 30 } ] 平均年龄 19.6 搜索张 [ { id: 1, name: 张三, age: 20 } ]这个案例用到了变量声明、模板字符串、forEach、map、filter、reduce、includes、解构赋值、默认参数、箭头函数、数组方法等多达十余个知识点。你可以尝试修改需求比如“删除用户”“按年龄排序”“支持编辑”来巩固对这些语法的掌握。9. 常见问题与排查思路新手写 JS 时最痛苦的就是“报错”。下面是几个常见问题、原因和解决思路。问题现象常见原因解决思路xxx is not defined变量名拼写错误或使用了未声明的变量检查拼写确认是否在当前作用域声明了该变量Cannot read property name of undefined访问了undefined或null的属性用console.log打印对象确认数据是否存在访问前加防御判断如if (obj obj.name)Unexpected token语法错误比如少写了括号、大括号、引号查看报错指向的行号和列号检查是否在中文输入法下写了中文符号NaN出现在运算结果中将非数字字符串当成了数字参与计算使用Number()、parseInt()、parseFloat()显式转换先校验数据类型使用判断导致意外成立隐式类型转换统一换成数据渲染出来全是[object Object]直接拼接了对象使用JSON.stringify(obj)或明确取对象的某个属性如obj.name异步请求拿不到数据没有等 Promise 完成就在外部访问了返回值在.then或async/await之后进行后续处理9.1 排查建议如果不确定哪里出了问题最高效的方式是“二分定位法”把代码分成几个部分用console.log打印中间结果逐步缩小问题范围。比如排查数据接口问题时先打印请求返回值再看是不是数据结构不符合预期。10. 最佳实践与工程建议语法只是第一步。想要写出可维护、不容易出 bug 的代码从学习阶段就该养成好习惯。10.1 命名规范变量、函数名使用“驼峰命名法”如userName、getUserList。常量名可以使用全大写下划线如MAX_COUNT。布尔类型变量建议用is、has、can开头如isLoading、hasPermission。const MAX_SIZE 100; let isLogin false; function getUserList() { }10.2 优先使用 const默认用const声明变量。只有当确实需要重新赋值时才改成let。这能在编码阶段就防止很多意外修改。10.3 函数单一职责一个函数只做一件事不要写一个“大杂烩”函数。比如“获取数据”和“渲染数据”要分开这样测试和维护都更容易。10.4 防御性编程对可能为空的参数做校验。比如用户输入年龄时传入的是一个数字还是一个字符串是否需要转成数字function addUser(name, age) { if (typeof name ! string || name.trim() ) { console.error(姓名不能为空); return; } const numericAge Number(age); if (Number.isNaN(numericAge) || numericAge 0) { console.error(年龄不合法); return; } // 后续逻辑... }10.5 异常处理异步代码如果可能失败一定要加try...catch或.catch()否则一旦出错程序可能直接中断用户也得不到任何提示。至少把错误打印出来方便排查。10.6 学习排错工具能力成长的关键之一是会用调试工具。除了console.log还推荐掌握 Chrome DevTools 的 Sources 面板断点调试。断点能让你逐行观察代码执行过程、变量的实时值比盲目打印日志高效得多。11. 总结与下一步学习建议到这里JS 最核心的语法体系你已经全部过了一遍变量、数据类型、运算符、流程控制、函数、字符串与数组、对象、Promise 异步处理还通过一个实战案例把知识点串了起来。30 分钟看完配合动手练习你离“能独立写前端交互”只有一步之遥。下一步该怎么走练把实战案例自己敲一遍尝试增加“按年龄从大到小排序”“删除指定 id 用户”等功能。学 DOM 操作学习document.getElementById、querySelector、addEventListener让 JS 真正操作网页元素。学请求接口掌握fetch和axios学会和服务器交换数据。学框架有了 JS 语法基础再学 Vue 或 React 会顺畅很多。前端面试题里反复出现的事件循环、闭包、防抖节流、this 指向等问题也可以逐步攻克。如果这篇文章对你有帮助可以收藏备用也欢迎边看边在 Console 里实际运行代码。动手是学会编程唯一的捷径。遇到任何报错先别急着怀疑人生把错误信息贴到搜索框里再看代码上下文通常都能找到答案。祝你在前端开发的路上越走越顺
网站建设高端定制企业官网