This repository has been archived on 2026-05-19. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
obsidian/FRONTEND/JavaScript 基础.md
T

4.6 KiB

tags, create time
tags create time
前端
JavaScript
基础
2026-04-24 18:41

JavaScript 基础

概述

JavaScript 是前端唯一的专业编程语言。它让网页从静态内容变成动态交互:点击按钮弹出对话框、表单验证、数据异步加载、动画效果……所有这些都需要 JS。

思考题:JavaScript 是单线程语言,那它如何实现"异步"而不阻塞页面?

正文

1. 变量与数据类型

// 三种变量声明方式
let name = "Alice";       // let:块级作用域,可重新赋值
const age = 25;           // const:块级作用域,不可重新赋值
var old = 10;             // var:函数作用域(老旧写法,尽量少用)

// JavaScript 的主要数据类型
let text = "Hello";        // string
let num = 42;              // number
let flag = true;           // boolean
let empty = null;          // null:有意为空
let notDefined;            // undefined:未赋值
let list = [1, 2, 3];      // array
let person = { name: "Alice" }; // object
graph LR
    A[JavaScript 数据类型] --> B[原始类型 Primitive]
    A --> C[引用类型 Reference]
    B --> D[string]
    B --> E[number]
    B --> F[boolean]
    B --> G[null]
    B --> H[undefined]
    B --> I[Symbol]
    B --> J[BigInt]
    C --> K[array]
    C --> L[object]
    C --> M[Function]

提问: typeof null 返回 "object" 是 JavaScript 的历史 bug 吗?为什么这个 bug 至今没有修复?

2. 函数

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

// 箭头函数(ES6+ 推荐)
const multiply = (a, b) => a * b;

// 默认参数
const greet = (name = "World") => `Hello, ${name}!`;

// 函数作为参数(高阶函数)
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);    // [2, 4, 6, 8, 10]
const evens = numbers.filter(n => n % 2 === 0); // [2, 4]
const sum = numbers.reduce((acc, n) => acc + n, 0); // 15

核心概念: map / filter / reduce 是函数式编程的核心三件套,也是 React 中处理数据的核心模式。

3. DOM 操作

// 获取元素
const btn = document.getElementById("submit-btn");
const items = document.querySelectorAll(".item");

// 修改内容
btn.textContent = "点击我";
btn.innerHTML = "<strong>加粗文字</strong>";

// 修改样式
btn.style.backgroundColor = "blue";
btn.classList.add("active");    // 添加 class
btn.classList.toggle("hidden"); // 切换 class

// 创建元素
const newDiv = document.createElement("div");
newDiv.textContent = "动态创建的元素";
document.body.appendChild(newDiv);

// 事件监听
btn.addEventListener("click", () => {
    alert("按钮被点击了!");
});

4. 异步编程 — 前端最核心的难点

// 方式一:Promise
fetch("https://api.example.com/users")
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error(error));

// 方式二:async/await(推荐,更直观)
async function getUsers() {
    try {
        const response = await fetch("https://api.example.com/users");
        const data = await response.json();
        console.log(data);
    } catch (error) {
        console.error("请求失败:", error);
    }
}
sequenceDiagram
    participant U as 用户
    participant B as 浏览器
    participant S as 服务器
    U->>B: 点击按钮
    B->>B: 触发 async 函数
    B->>S: fetch 请求发送
    Note over B: 页面不卡顿!(非阻塞)
    S-->>B: 返回 JSON 数据
    B->>B: .then() / await 处理数据
    B->>U: 更新页面内容

提问: Promise 的三种状态(pending / fulfilled / rejected)是如何流转的?为什么 async/await 本质上是 Promise 的语法糖?

5. 作用域与闭包

// 作用域链
function outer() {
    let count = 0;                    // 外层函数变量
    
    return function() {               // 内部函数"记住"了外层的 count
        count++;
        return count;
    };
}

const counter = outer();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

思考: 闭包是 JS 中最强大的特性之一,但它也被广泛用于实现单例模式、数据隐藏和回调函数。你能想到闭包在真实项目中的哪些应用场景?

关联笔记