JavaScript 使用与开发指南

本文是一份面向前端页面和主题开发的 JavaScript 实战指南,重点讲清楚语言基础、浏览器 DOM、事件、异步、模块、表单、请求、存储、性能、可访问性,以及在实际页面中如何组织脚本。它适合和 HTML、CSS、Nginx 静态资源、前端模板一起使用。

适用场景

  • 编写网页交互逻辑
  • 主题脚本开发
  • 表单提交和异步请求
  • DOM 操作和事件绑定
  • 页面性能优化和可访问性
  • 和后端 API 对接

JavaScript 是什么

JavaScript 是运行在浏览器和其他环境中的脚本语言。在前端页面里,它最常见的用途是:

  • 处理用户交互
  • 修改页面内容
  • 发起网络请求
  • 管理状态
  • 控制动画和局部刷新

运行环境

JavaScript 可以运行在:

  • 浏览器
  • Node.js
  • 服务端或边缘环境

本文主要关注浏览器场景。

基础语法

变量

let name = "Alice";
const age = 18;
var legacy = true;

建议:

  • 默认用 const
  • 需要重新赋值时用 let
  • 尽量少用 var

数据类型

  • string
  • number
  • boolean
  • null
  • undefined
  • object
  • symbol
  • bigint

条件

if (age >= 18) {
  console.log("adult");
} else {
  console.log("minor");
}

循环

for (let i = 0; i < 3; i++) {
  console.log(i);
}

for (const item of [1, 2, 3]) {
  console.log(item);
}

函数

function greet(name) {
  return `Hello, ${name}`;
}

const add = (a, b) => a + b;

严格模式

严格模式可以减少一些隐式错误。

"use strict";

现代模块环境中通常默认更严格,但在老脚本里仍值得显式使用。

数组与对象

数组

const list = [1, 2, 3];
list.push(4);
const doubled = list.map((n) => n * 2);

对象

const user = {
  name: "Alice",
  age: 18,
};

解构

const { name, age } = user;
const [first, second] = list;

展开

const nextUser = { ...user, role: "admin" };
const nextList = [...list, 5];

DOM 操作

选择元素

querySelector() 会返回匹配到的第一个元素,找不到时返回 null

const btn = document.querySelector("#submit");
const items = document.querySelectorAll(".item");

修改内容

const el = document.querySelector("#title");
el.textContent = "New Title";

修改属性

const img = document.querySelector("img");
img.setAttribute("alt", "Banner");

类名操作

el.classList.add("active");
el.classList.remove("active");
el.classList.toggle("hidden");

建议:

  • 优先用 textContent
  • 少用 innerHTML
  • 对用户输入务必防止 XSS

事件

绑定事件

button.addEventListener("click", () => {
  console.log("clicked");
});

表单提交

form.addEventListener("submit", (event) => {
  event.preventDefault();
});

常见事件

  • click
  • input
  • change
  • submit
  • focus
  • blur
  • keydown
  • scroll

异步编程

JavaScript 的异步是核心能力之一。

回调

setTimeout(() => {
  console.log("later");
}, 1000);

Promise

Promise 表示一个未来完成或失败的操作。

const promise = new Promise((resolve) => {
  resolve("ok");
});

async / await

async function loadData() {
  const res = await fetch("/api/data");
  return await res.json();
}

建议:

  • 需要顺序执行的异步逻辑,用 async/await
  • 需要并发执行的,考虑 Promise.all

并发

const [a, b] = await Promise.all([fetch("/a"), fetch("/b")]);

Fetch

Fetch 是现代浏览器里最常用的请求方式。

GET 请求

const res = await fetch("/api/user");
const data = await res.json();

POST 请求

await fetch("/api/message", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ name: "Alice" }),
});

错误处理

try {
  const res = await fetch("/api/data");
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  const data = await res.json();
  console.log(data);
} catch (err) {
  console.error(err);
}

表单处理

前端表单的关键点是:

  • 校验
  • 提示
  • 禁用重复提交
  • 处理成功和失败状态

示例:

form.addEventListener("submit", async (e) => {
  e.preventDefault();
  submitBtn.disabled = true;
  try {
    const formData = new FormData(form);
    const res = await fetch("/api/submit", {
      method: "POST",
      body: formData,
    });
    if (!res.ok) throw new Error("submit failed");
  } finally {
    submitBtn.disabled = false;
  }
});

存储

localStorage

localStorage.setItem("theme", "dark");
const theme = localStorage.getItem("theme");

sessionStorage

适合当前会话。

Cookie

用于需要随请求发送到服务端的数据。不要把敏感信息明文放进前端可控存储。

模块

导出

export function sum(a, b) {
  return a + b;
}

导入

import { sum } from "./utils.js";

模块化的好处:

  • 更容易维护
  • 依赖更清晰
  • 便于拆分代码

浏览器 API

常见有用 API:

  • window
  • document
  • location
  • history
  • navigator
  • localStorage
  • fetch
  • URL
  • FormData

URL

const url = new URL(location.href);
console.log(url.searchParams.get("page"));

FormData

const formData = new FormData(form);

性能

资源加载

MDN 建议,对外部脚本优先考虑 defer,避免阻塞页面解析。

<script src="/static/js/app.js" defer></script>

避免阻塞

  • 大脚本放底部或使用 defer
  • 不要无脑用大量同步 DOM 操作
  • 避免频繁重排重绘

防抖和节流

function debounce(fn, delay) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), delay);
  };
}

可访问性

使用语义化元素

  • 按钮用 <button>
  • 链接用 <a>
  • 表单控件配 label

键盘可用

交互不要只依赖鼠标点击。

可读的状态

按钮禁用、加载中、错误提示要让用户能感知。

安全

XSS

不要把不可信内容直接塞进 innerHTML

URL 注入

构建链接时注意编码和校验。

CSRF

前端请求时要配合后端的 CSRF 策略。

常见写法建议

  • 先拿 DOM,再绑定事件
  • 逻辑拆成小函数
  • 数据和 UI 分开
  • 用早返回减少嵌套
  • 尽量避免全局变量

和你仓库中的主题系统关系

你仓库里的主题模板里已经有一些典型 JS 用法:

  • 导航菜单切换
  • 轮播图
  • 表单提交
  • 验证码刷新
  • fetch() 请求

这说明 JS 代码更适合被拆成:

  • 公共脚本
  • 页面脚本
  • 组件脚本

而不是所有逻辑都堆在一个大文件里。

最小可用模板

<script defer src="/static/js/app.js"></script>
document.addEventListener("DOMContentLoaded", () => {
  const btn = document.querySelector("#menu-btn");
  const menu = document.querySelector("#menu");
  if (!btn || !menu) return;
  btn.addEventListener("click", () => {
    menu.classList.toggle("open");
  });
});

常见问题

1. null 取到报错

说明选择器没匹配到元素。先判断元素是否存在。

2. 请求失败

检查:

  • URL 是否正确
  • CORS 是否放行
  • 服务器是否返回非 2xx

3. 页面卡顿

检查:

  • 事件里是否做了太多 DOM 操作
  • 是否频繁读取和写入布局属性
  • 是否有大循环

4. 脚本不执行

检查:

  • script 标签路径
  • defer / async
  • DOM 是否已加载

结论

JavaScript 的核心不是“会不会写几句语法”,而是:

  • 理解浏览器事件模型
  • 能正确操作 DOM
  • 能处理异步和请求
  • 会组织模块和状态
  • 能保证可访问性和安全性

如果你要,我可以继续把这篇文档扩成更深入的版本,例如:

  • JavaScript 异步与 Promise 深度指南
  • DOM 与事件实战模板
  • 前端安全与 XSS 防护
  • Node.js 基础入门
  • 现代 JavaScript 模块化与工程化
本文地址: https://www.vvcms.cn/blog/js-guid
版权所有 © admin 未经授权不得转载