JavaScript 入门:让网页动起来
HTML 搭骨架,CSS 上妆面。但一个页面如果只有这两样,用户点按钮不会有反应、表单不会校验、数据不会从服务器加载。让网页活过来的东西,是 JavaScript。
JavaScript 是什么
JavaScript 最初是浏览器里跑的脚本语言——嵌入 HTML 页面,操作 DOM,响应用户交互。1995 年 Brendan Eich 花了 10 天写出第一个版本,今天已经是全世界使用最广的编程语言之一。
它的核心特征:
- 动态类型 — 变量不用声明类型,运行时决定
- 事件驱动 — 用户点击、键盘输入、网络响应都能绑定处理函数
- 单线程 + 异步 — 一次干一件事,但用事件循环(Event Loop)处理耗时操作不阻塞界面
加一段 JS 到页面
最直接的方式是用 <script> 标签。放在 </body> 前面,确保 DOM 已加载完毕:
<script>
console.log('页面加载完毕');
</script>
实际项目中很少写内联 JS。白物集的 Astro 页面用单独的 .astro 文件组织脚本,一个典型的组件文件长这样:
---
// 服务端脚本(构建时执行)
const title = 'Hello';
---
<!-- 模板 -->
<h1>{title}</h1>
<script>
// 客户端脚本(浏览器中执行)
document.querySelector('h1').style.color = 'blue';
</script>
Astro 的 <script> 标签默认会被打包、tree-shaking,只把真正用到的代码发送给浏览器。
变量声明:let 和 const
白物集 API 代码里只用 const 和 let,不用 var。这是 ES6(2015)引入的规范,作用域更清晰:
const PORT = parseInt(process.env.PORT || '3001'); // 常量,不可重新赋值
let count = 0; // 可变
count += 1;
经验: 大部分场景用 const。如果你不确定一个变量会不会重新赋值,先写 const——编辑器会告诉你是否需要改成 let。白物集 19 个 API 路由文件里,const 出现超过 200 次,let 不到 20 次。
函数:箭头的时代
白物集代码里几乎看不到 function 关键字。全部用箭头函数:
// health.js — 健康检查接口
router.get('/', (req, res) => {
const data = {
status: 'ok',
service: 'baiwuji-api',
version: '2.0.0',
time: new Date().toISOString(),
};
res.json(data);
});
箭头函数 (参数) => { 函数体 } 比传统函数更简洁,而且不绑定自己的 this——这在事件处理和回调场景中省去了大量 var self = this 的样板代码。
异步操作用 async/await 语法。白物集的 api.js 封装了 SSR 层 API 客户端,从 Astro 服务端发请求给后端 Express:
async function get(path) {
const res = await fetch(BASE + API_PREFIX + path);
if (!res.ok) {
const body = await res.text().catch(() => '');
throw new Error(`API ${res.status}: ${body.slice(0, 100)}`);
}
return res.json();
}
async function 声明这是一个异步函数。await fetch(...) 等待网络请求完成,不阻塞事件循环。await res.text() 读取响应体。三行代码完成一次完整的 HTTP 请求——换成回调写法至少多一层嵌套。
数据类型:比你想象的少
JavaScript 只有七种基本类型:string、number、boolean、null、undefined、symbol、bigint。其余全是对象(Object)。
实际开发中打交道最多的是:
const title = '白物集'; // string
const views = 42; // number
const isPublished = true; // boolean
const tags = ['JS', '教程']; // Array(也是一种对象)
const article = { // Object
title: 'JavaScript 入门',
slug: 'js-intro',
published: true,
};
白物集的错误处理模块 errors.js 用对象常量做状态码映射:
const ERROR_CODES = {
VALIDATION_ERROR: 'VALIDATION_ERROR',
NOT_FOUND: 'NOT_FOUND',
UNAUTHORIZED: 'UNAUTHORIZED',
INTERNAL_ERROR: 'INTERNAL_ERROR',
};
这种模式比硬编码字符串好——编辑器自动补全、改名时全局同步、拼写错误会编译报错。
操作 DOM
浏览器给 JavaScript 提供了 document 对象,用来查询和修改页面结构。下面是白物集文章页的客户端交互脚本的关键片段:
// 点赞
document.getElementById('like-btn').addEventListener('click', async () => {
const res = await fetch(`/api/v1/likes/${articleId}/like`, { method: 'POST' });
const data = await res.json();
document.getElementById('like-count').textContent = data.likes;
});
addEventListener 是绑定事件的现代方式。click、submit、scroll、keydown——浏览器定义了几十种事件类型。把处理函数挂上去,页面就有交互了。
最常见的坑
1. == 和 === 不分
console.log(1 == '1'); // true(类型转换后比较)
console.log(1 === '1'); // false(类型不同直接返回 false)
白物集代码只用 === 和 !==。建议你也这样——== 的类型转换规则有十几个例外,记不住的。
2. 异步结果当同步用
// ❌ data 是 Promise 对象,不是结果
const data = fetch('/api/data');
console.log(data); // Promise { <pending> }
// ✅ 用 await 拿结果
const res = await fetch('/api/data');
const data = await res.json();
3. const 对象的内容可以改
const obj = { name: '白物集' };
obj.name = '白物集 2.0'; // ✅ 可以,const 保护的是引用而非内容
// obj = {} ❌ 不能重新赋值
怎么调试
永远别用 alert() 调试。 白物集开发时调试工具链:
console.log()— 打点输出,浏览器 F12 → Console 面板查看- 浏览器 DevTools — Sources 面板下断点,逐行执行,看变量值变化
- Network 面板 — 看 API 请求和响应,状态码、耗时、载荷
白物集的 API 请求中间件本身就用了 logger.info 记录每次请求的方法、路径、状态码和耗时:
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
logger.info({
method: req.method,
path: req.originalUrl || req.url,
status: res.statusCode,
durationMs: Date.now() - start,
}, 'request');
});
next();
});
这段代码在生产环境记录每一次 API 调用——你按 F12 打开 Network 面板看到的请求耗时,和服务器日志里记录的一致。前后端对得上。
浏览器的开发者工具
Chrome 的 DevTools(F12)是前端开发的标配。几个最常用的面板:
- Elements — 实时查看 DOM 结构、修改 CSS
- Console — 执行 JS、看输出、看错误堆栈
- Sources — 下断点、单步执行
- Network — 看请求瀑布图、响应体、请求头
你打开白物集的文章页面,按 F12 → Console,输入 document.title,就能看到当前页面的标题。这是你第一次用 JavaScript 和真实网页交互。
下一篇预告
你学会了在浏览器里运行 JS、操作 DOM、处理事件。但 JavaScript 真正强大的地方不在于操作当前页面,而在于向服务器要数据并渲染——那就是 Fetch API 和异步编程要讲的内容。
下一篇:DOM 操作:JavaScript 如何控制页面,深入 querySelector、元素创建、事件委托、以及白物集「交叉推荐」组件如何用纯 JS 渲染。