CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
前端入门实战/课时/JavaScript
RawBlame
课时目录12 节

前端入门实战

  1. 01HTML
  2. 02CSS
  3. 03JavaScript
  4. 04Git
  5. 05GitHub
  6. 06npm
  7. 07React
  8. 08Tailwind
  9. 09Vitest
  10. 10综合练习
  11. 11部署预览
  12. 12路线图对照

JavaScript

DOM 与 ES 基础。

35 分钟

JavaScript:变量、函数与 DOM 操作

这一课你将能做到

  1. 用变量、函数、条件判断和循环写出可复用的逻辑代码
  2. 用 DOM API 读取和修改页面内容,实现点击按钮更新文字
  3. 用事件监听和 ES6+ 语法(箭头函数、解构、模板字符串)写出符合现代规范的代码

为什么要学

HTML 给结构,CSS 给样式,JavaScript 给行为。没有 JS,网页就是一张静止的画;有了 JS,它可以响应点击、提交表单、拉取数据、动态更新内容。现代前端工程师写的代码,80% 以上是 JavaScript。

对初学者来说,JS 的门槛在于它同时有「命令式编程」(一步步告诉电脑怎么做)和「声明式/函数式」两种风格,浏览器环境还引入了异步、事件循环等概念。但入门阶段只需要掌握基础语法和 DOM 操作,就能做出真正有交互的页面。

先建立图像

浏览器内部执行 JS 的流程:

你写的 .js 文件
    ↓
浏览器解析 → 变量提升 → 执行代码 → 操作 DOM/发请求
    ↓
DOM 树发生变化 → 浏览器重绘页面 → 用户看到变化

JS 是单线程的,同一时间只能做一件事,但事件循环让它看起来像「同时做多件事」。这个概念后面会深入,入门阶段先记住:代码从上到下执行,事件回调在主线空闲时执行。

跟着做

步骤 1:变量、数据类型与运算符

新建 script.js,在 index.html 的 </body> 前引入:

<script src="script.js"></script>
// 变量声明:const 不可重新赋值,let 可重新赋值
const siteName = "学习站";
let visitCount = 0;

// 基本数据类型
const isActive = true;          // 布尔
const price = 199.9;            // 数字(JS 不区分 int 和 float)
const description = "前端课程";   // 字符串
const tags = ["html", "css", "js"]; // 数组
const user = {                  // 对象
    name: "张三",
    age: 25,
    isVip: false
};

// 模板字符串:反引号 + ${}
const greeting = `欢迎来到 ${siteName},当前访客数 ${visitCount}`;
console.log(greeting);

// 运算符
visitCount++;                   // 自增
const total = price * 1.2;      // 算术
const canAccess = user.isVip || price === 0; // 逻辑
const hasTag = tags.includes("css"); // 数组方法

建议:默认用 const,只有需要重新赋值时才用 let。不要用 var,它有作用域提升问题,在现代代码中已淘汰。

步骤 2:函数与箭头函数

// 传统函数声明
function add(a, b) {
    return a + b;
}

// 函数表达式
const multiply = function (a, b) {
    return a * b;
};

// 箭头函数(现代项目最常用)
const divide = (a, b) => a / b;

// 多行箭头函数需要 return
const formatUser = (user) => {
    const level = user.age >= 18 ? "成年" : "未成年";
    return `${user.name}(${level})`;
};

console.log(add(2, 3));          // 5
console.log(formatUser(user));   // 张三(成年)

箭头函数和传统函数有一个关键区别:this 的绑定方式不同。入门阶段先记住:回调函数(比如事件监听、数组方法)优先用箭头函数,类方法或需要动态 this 时用传统函数。

步骤 3:条件判断与循环

// if / else
function getDiscount(user) {
    if (user.isVip) {
        return 0.8;
    } else if (user.age >= 60) {
        return 0.9;
    } else {
        return 1.0;
    }
}

// 三元表达式(简短条件)
const statusText = user.isVip ? "VIP 用户" : "普通用户";

// 循环
for (let i = 0; i < tags.length; i++) {
    console.log(tags[i]);
}

// 数组高阶方法(现代写法,推荐)
tags.forEach((tag) => console.log(tag));

const upperTags = tags.map((tag) => tag.toUpperCase());
console.log(upperTags); // ["HTML", "CSS", "JS"]

const longTags = tags.filter((tag) => tag.length > 2);
console.log(longTags);  // ["html", "css"]

map、filter、forEach 是 JS 数组三大高阶方法,实际工作中出现的频率极高,必须熟练。

步骤 4:DOM 操作

DOM(Document Object Model)是浏览器把 HTML 解析成的树形结构,JS 通过 DOM API 来读写页面:

// 读取元素
const title = document.querySelector("h1");
const items = document.querySelectorAll(".item");

// 修改内容
title.textContent = "新标题";

// 修改样式
title.style.color = "#e63946";

// 修改属性
title.setAttribute("data-level", "1");

// 创建并插入元素
const newDiv = document.createElement("div");
newDiv.className = "card";
newDiv.textContent = "动态添加的内容";
document.body.appendChild(newDiv);

// 删除元素
const old = document.querySelector(".old");
if (old) old.remove();

querySelector 和 querySelectorAll 是万能选择器,支持 CSS 选择器语法,已经取代了旧的 getElementById/getElementsByClassName。

步骤 5:事件监听

<button id="clickBtn">点击我</button>
<input id="nameInput" placeholder="输入名字">
<p id="output"></p>
const btn = document.querySelector("#clickBtn");
const input = document.querySelector("#nameInput");
const output = document.querySelector("#output");

// 点击事件
btn.addEventListener("click", () => {
    output.textContent = `你好,${input.value || "访客"}!`;
});

// 输入事件(实时响应)
input.addEventListener("input", (event) => {
    output.textContent = `正在输入:${event.target.value}`;
});

事件监听是现代 JS 交互的核心模式:addEventListener 绑定事件 → 用户触发 → 回调函数执行 → 操作 DOM → 页面更新。

步骤 6:ES6+ 常用语法

// 解构赋值
const { name, age } = user;
const [first, second] = tags;

// 展开运算符
const newTags = [...tags, "react"];
const newUser = { ...user, city: "北京" };

// 默认参数
const greet = (name = "访客") => `你好,${name}`;

// 可选链(防止深层对象报错)
const city = user?.address?.city ?? "未知";

// Promise 基础(异步操作)
function fetchData() {
    return fetch("https://api.github.com/users/github")
        .then((res) => res.json())
        .then((data) => console.log(data.login))
        .catch((err) => console.error("出错了", err));
}

讲清楚要点

  1. JS 是弱类型语言:变量不声明类型,同一变量可以先存数字再存字符串。类型转换时要小心:"5" + 1 等于 "51","5" - 1 等于 4。
  2. == 和 === 的区别:== 会做类型转换后比较("5" == 5 为 true),=== 要求类型和值都相同。始终用 === 和 !==,避免隐式转换的坑。
  3. 数组方法不改变原数组:map、filter、slice 返回新数组;push、pop、splice 改变原数组。React 中尤其要注意,优先用不可变方法。
  4. DOM 操作是同步但昂贵的:每次修改 DOM 都可能触发浏览器重排(reflow)和重绘(repaint)。频繁修改时先操作文档片段,或一次性修改完。
  5. 事件委托减少监听器数量:如果列表有 100 个 item,不要给每个 item 绑点击事件,而是给父容器绑一个,通过 event.target 判断点的是谁。

你可能会懵的地方

  • 为什么 var 不能用? var 是函数作用域,会提升到函数顶部,在循环中容易出现闭包陷阱。let 和 const 是块级作用域({} 内有效),行为更可预期。

  • this 到底指向谁? 简单规则:普通函数里 this 指向调用者;箭头函数里 this 指向定义时的上下文(外层作用域)。事件回调用箭头函数可以避免 this 指向事件目标的问题。

  • 为什么我的 DOM 操作报错 null? <script> 放在 <head> 里时,JS 执行时 body 还没解析。解决:把 <script> 放在 </body> 前,或加 defer 属性:<script src="..." defer></script>。

  • null 和 undefined 有什么区别? undefined 表示「声明了但还没赋值」;null 表示「赋值为空」。typeof null 是 "object",这是 JS 的历史 bug,记住就行。

  • Promise 和 async/await 是什么关系? async/await 是 Promise 的语法糖,让异步代码看起来像同步。入门阶段先会用 fetch().then(),后面再学 async function 和 await。

错法对照

错法问题正解
var x = 1作用域提升、不可预期const / let
"5" == 5隐式类型转换导致误判始终用 ===
const arr = []; arr.push(1)误以为 const 数组不可改const 锁引用,不锁内容
document.querySelector("btn")少了 # 或 .按 CSS 选择器写:#btn
<script> 放 head 且无 deferDOM 未就绪就执行放 body 末尾或用 defer
for (var i=0; i<3; i++) { setTimeout(..., i) }var 提升导致输出全是 3用 let 或传参
user.name 时 user 是 undefined直接报错中断执行用可选链 user?.name

卡点急救

  1. 控制台报错 Cannot read properties of null:选择器写错,或 JS 在 DOM 加载前执行。检查选择器语法、script 标签位置。
  2. 点击按钮没反应:检查 addEventListener 的拼写、事件名(是 "click" 不是 "onclick")、选择器是否命中元素。
  3. 数组 map 后页面没更新(React 中):React 要求不可变更新,不能直接 push,要用 setState([...old, newItem])。
  4. fetch 请求报 CORS 错:浏览器安全策略限制,不是代码问题。自己的后端加 CORS 头,或前端用代理。

面试常问

  • == 和 === 的区别? == 比较前会做类型转换,=== 严格比较值和类型。推荐始终用 ===。

  • 什么是闭包? 函数内部引用了外部作用域的变量,即使外部函数已经执行完毕,这些变量仍被保留。常用于数据封装、柯里化、事件回调保留状态。

  • 事件冒泡和事件捕获? 事件从目标元素向外传递到 document 叫冒泡(bubble);从 document 向内传到目标叫捕获(capture)。默认是冒泡阶段触发。stopPropagation() 阻止继续冒泡。

  • let、const、var 的区别? var 函数作用域、可重复声明、存在提升;let 和 const 块级作用域、不可重复声明、const 声明后不能重新赋值引用。TDZ(暂时性死区):let/const 声明前访问会报错。

自测三问

  1. 写出一段代码:点击按钮,读取 input 的值,在页面上显示「你好,xxx」。
  2. map 和 forEach 的区别是什么?各自返回什么?
  3. 用解构赋值从 { name: "A", age: 20 } 中取出 name,并给 age 一个默认值 18。

小结一句话

JavaScript 用变量存数据、用函数封装逻辑、用 DOM API 连接页面——三者结合,你就能写出有交互的真实网页。

延伸

  • MDN JavaScript 基础
  • 下一课:Git——管理代码版本,再也不怕改坏代码回不去。
加载本节练习…
← 上一课CSS下一课 →Git