JavaScript 学习指南

本指南包含 JavaScript 的核心特性、详细注释和实例代码,帮助您快速学习 JavaScript。

1. JavaScript 基础

1.1 变量和数据类型

// 变量声明
var name = "张三"; // 函数作用域
let age = 25;     // 块级作用域
const PI = 3.14;  // 常量,不可修改

// 数据类型
let str = "Hello";           // 字符串
let num = 10;                // 数字
let bool = true;             // 布尔值
let arr = [1, 2, 3];         // 数组
let obj = { name: "张三", age: 25 }; // 对象
let nullValue = null;         // 空值
let undefinedValue;           // 未定义
let symbolValue = Symbol("id"); // 唯一值
let bigIntValue = 9007199254740991n; // 大整数

// 类型转换
let numToString = String(num); // 数字转字符串
let strToNum = Number(str);    // 字符串转数字
let boolToNum = Number(bool);  // 布尔值转数字
let numToBool = Boolean(num);  // 数字转布尔值

// 类型检查
typeof str;     // "string"
typeof num;     // "number"
typeof bool;    // "boolean"
typeof arr;     // "object"
typeof obj;     // "object"
typeof nullValue; // "object" (历史遗留问题)
typeof undefinedValue; // "undefined"
typeof symbolValue; // "symbol"
typeof bigIntValue; // "bigint"

// 数组类型检查
Array.isArray(arr); // true

// 空值检查
nullValue === null; // true
undefinedValue === undefined; // true

// 真值和假值
// 假值:false, 0, "", null, undefined, NaN
// 真值:除了假值以外的所有值

实例:变量和数据类型

1.2 运算符

// 算术运算符
let a = 10, b = 3;
console.log(a + b); // 13
console.log(a - b); // 7
console.log(a * b); // 30
console.log(a / b); // 3.333...
console.log(a % b); // 1 (余数)
console.log(a ** b); // 1000 (幂)

// 自增自减
let c = 5;
console.log(c++); // 5 (先使用后自增)
console.log(++c); // 7 (先自增后使用)
console.log(c--); // 7 (先使用后自减)
console.log(--c); // 5 (先自减后使用)

// 赋值运算符
let d = 10;
d += 5; // d = d + 5
d -= 3; // d = d - 3
d *= 2; // d = d * 2
d /= 4; // d = d / 4

// 比较运算符
console.log(5 > 3); // true
console.log(5 < 3); // false
console.log(5 >= 5); // true
console.log(5 <= 3); // false
console.log(5 == "5"); // true (类型转换)
console.log(5 === "5"); // false (严格相等)
console.log(5 != "5"); // false (类型转换)
console.log(5 !== "5"); // true (严格不相等)

// 逻辑运算符
console.log(true && false); // false (与)
console.log(true || false); // true (或)
console.log(!true); // false (非)

// 三元运算符
let age = 18;
let status = age >= 18 ? "成年人" : "未成年人";

// 字符串运算符
let str1 = "Hello", str2 = "World";
console.log(str1 + " " + str2); // "Hello World"
console.log(`${str1} ${str2}`); // "Hello World" (模板字符串)

实例:运算符

2. 控制流

2.1 条件语句

// if 语句
if (条件) {
    // 条件为真时执行
} else if (另一个条件) {
    // 另一个条件为真时执行
} else {
    // 所有条件都为假时执行
}

// 示例
let age = 18;
if (age < 18) {
    console.log("未成年人");
} else if (age >= 18 && age < 60) {
    console.log("成年人");
} else {
    console.log("老年人");
}

// switch 语句
switch (表达式) {
    case 值1:
        // 表达式等于值1时执行
        break;
    case 值2:
        // 表达式等于值2时执行
        break;
    default:
        // 表达式不等于任何值时执行
        break;
}

// 示例
let day = "Monday";
switch (day) {
    case "Monday":
        console.log("星期一");
        break;
    case "Tuesday":
        console.log("星期二");
        break;
    default:
        console.log("其他天");
        break;
}

2.2 循环语句

// for 循环
for (初始化; 条件; 更新) {
    // 循环体
}

// 示例:遍历数组
let arr = [1, 2, 3, 4, 5];
for (let i = 0; i < arr.length; i++) {
    console.log(arr[i]);
}

// for...of 循环(ES6+)
for (let element of arr) {
    console.log(element);
}

// for...in 循环(遍历对象属性)
let obj = { name: "张三", age: 25 };
for (let key in obj) {
    console.log(key + ": " + obj[key]);
}

// while 循环
while (条件) {
    // 循环体
}

// 示例
let i = 0;
while (i < 5) {
    console.log(i);
    i++;
}

// do...while 循环
do {
    // 循环体
} while (条件);

// 示例
let j = 0;
do {
    console.log(j);
    j++;
} while (j < 5);

// break 和 continue
for (let i = 0; i < 10; i++) {
    if (i === 5) {
        break; // 跳出循环
    }
    if (i % 2 === 0) {
        continue; // 跳过当前循环,进入下一次循环
    }
    console.log(i);
}

实例:控制流

3. 函数

3.1 函数声明

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

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

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

// 带函数体的箭头函数
const divide = (a, b) => {
    if (b === 0) {
        return "除数不能为0";
    }
    return a / b;
};

// 立即执行函数表达式 (IIFE)
(function() {
    console.log("立即执行函数");
})();

// 函数参数默认值(ES6+)
function greet(name = "匿名") {
    return `Hello, ${name}!`;
}

// 剩余参数(ES6+)
function sum(...numbers) {
    return numbers.reduce((total, num) => total + num, 0);
}

// 展开运算符(ES6+)
let arr = [1, 2, 3];
console.log(sum(...arr)); // 6

// 函数作用域
function outer() {
    let outerVar = "外部变量";
    
    function inner() {
        let innerVar = "内部变量";
        console.log(outerVar); // 可以访问外部变量
    }
    
    inner();
    // console.log(innerVar); // 不能访问内部变量
}

// 闭包
function createCounter() {
    let count = 0;
    
    return function() {
        count++;
        return count;
    };
}

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

实例:函数

4. 对象和数组

4.1 对象

// 对象字面量
let person = {
    name: "张三",
    age: 25,
    greet: function() {
        return `Hello, my name is ${this.name}`;
    },
    // 简写方法(ES6+)
    sayAge() {
        return `I am ${this.age} years old`;
    }
};

// 访问对象属性
console.log(person.name); // "张三"
console.log(person["age"]); // 25

// 修改对象属性
person.age = 26;
person["name"] = "李四";

// 添加新属性
person.gender = "男";

// 删除属性
delete person.gender;

// 遍历对象
for (let key in person) {
    console.log(key + ": " + person[key]);
}

// 检查属性是否存在
console.log("name" in person); // true
console.log(person.hasOwnProperty("age")); // true

// 对象方法
console.log(person.greet()); // "Hello, my name is 李四"
console.log(person.sayAge()); // "I am 26 years old"

// 对象解构(ES6+)
const { name, age } = person;
console.log(name, age); // "李四" 26

// 展开运算符(ES6+)
const personCopy = { ...person };
const personWithAddress = { ...person, address: "北京" };

// 原型
function Person(name, age) {
    this.name = name;
    this.age = age;
}

Person.prototype.greet = function() {
    return `Hello, my name is ${this.name}`;
};

const person1 = new Person("张三", 25);
console.log(person1.greet()); // "Hello, my name is 张三"

// 类(ES6+)
class PersonClass {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    
    greet() {
        return `Hello, my name is ${this.name}`;
    }
}

const person2 = new PersonClass("李四", 30);
console.log(person2.greet()); // "Hello, my name is 李四"

4.2 数组

// 数组字面量
let arr = [1, 2, 3, 4, 5];

// 访问数组元素
console.log(arr[0]); // 1
console.log(arr[arr.length - 1]); // 5

// 修改数组元素
arr[0] = 10;

// 添加元素
arr.push(6); // 添加到末尾
arr.unshift(0); // 添加到开头

// 删除元素
arr.pop(); // 删除末尾元素
arr.shift(); // 删除开头元素

// 数组长度
console.log(arr.length); // 5

// 遍历数组
// for 循环
for (let i = 0; i < arr.length; i++) {
    console.log(arr[i]);
}

// for...of 循环
for (let element of arr) {
    console.log(element);
}

// forEach 方法
arr.forEach((element, index) => {
    console.log(index + ": " + element);
});

// 数组方法
// map:返回新数组,每个元素经过处理
const doubled = arr.map(element => element * 2);

// filter:返回满足条件的元素
const even = arr.filter(element => element % 2 === 0);

// reduce:累加计算
const sum = arr.reduce((total, element) => total + element, 0);

// find:返回第一个满足条件的元素
const found = arr.find(element => element > 3);

// findIndex:返回第一个满足条件的元素索引
const index = arr.findIndex(element => element > 3);

// every:所有元素都满足条件
const allPositive = arr.every(element => element > 0);

// some:至少有一个元素满足条件
const hasEven = arr.some(element => element % 2 === 0);

// includes:检查数组是否包含某个元素
const hasThree = arr.includes(3);

// join:将数组元素连接成字符串
const str = arr.join(", ");

// slice:返回数组的一部分
const sliced = arr.slice(1, 3); // 从索引 1 到 2

// splice:修改原数组,删除或添加元素
arr.splice(1, 2, 10, 20); // 从索引 1 开始删除 2 个元素,添加 10 和 20

// 数组解构(ES6+)
const [first, second, ...rest] = arr;
console.log(first, second, rest);

// 展开运算符(ES6+)
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]

实例:对象和数组

5. DOM 操作

5.1 选择元素

// 通过 ID 选择元素
const element = document.getElementById("id");

// 通过类名选择元素(返回集合)
const elements = document.getElementsByClassName("class");

// 通过标签名选择元素(返回集合)
const elements = document.getElementsByTagName("tag");

// 通过 CSS 选择器选择元素
const element = document.querySelector("selector"); // 返回第一个匹配元素
const elements = document.querySelectorAll("selector"); // 返回所有匹配元素

// 示例
const header = document.getElementById("header");
const paragraphs = document.getElementsByTagName("p");
const activeElements = document.getElementsByClassName("active");
const firstParagraph = document.querySelector("p");
const allParagraphs = document.querySelectorAll("p");

5.2 修改元素

// 修改内容
const element = document.getElementById("element");
element.textContent = "新内容";
// 或
element.innerHTML = "新内容";

// 修改属性
element.setAttribute("class", "new-class");
element.getAttribute("class");
element.removeAttribute("class");

// 修改样式
element.style.color = "red";
element.style.fontSize = "16px";
element.style.backgroundColor = "#f0f0f0";

// 添加/移除类
element.classList.add("class-name");
element.classList.remove("class-name");
element.classList.toggle("class-name"); // 切换类
element.classList.contains("class-name"); // 检查是否包含类

5.3 创建和删除元素

// 创建元素
const div = document.createElement("div");
div.textContent = "新元素";
div.className = "new-element";

// 添加元素
const container = document.getElementById("container");
container.appendChild(div); // 添加到末尾

// 在指定位置插入元素
const referenceElement = document.getElementById("reference");
container.insertBefore(div, referenceElement); // 插入到 referenceElement 之前

// 删除元素
container.removeChild(div);
// 或
div.remove(); // 直接删除自己

// 克隆元素
const clonedElement = div.cloneNode(true); // true 表示深克隆

实例:DOM 操作

这是一个段落

6. 事件处理

6.1 事件监听器

// 方法 1:内联事件
<button onclick="handleClick()">点击</button>

// 方法 2:DOM 属性
const button = document.getElementById("button");
button.onclick = function() {
    console.log("点击事件");
};

// 方法 3:addEventListener(推荐)
button.addEventListener("click", function() {
    console.log("点击事件");
});

// 移除事件监听器
function handleClick() {
    console.log("点击事件");
}

button.addEventListener("click", handleClick);
button.removeEventListener("click", handleClick);

// 事件对象
element.addEventListener("click", function(event) {
    console.log(event.target); // 事件目标
    console.log(event.type); // 事件类型
    console.log(event.clientX, event.clientY); // 鼠标坐标
    event.preventDefault(); // 阻止默认行为
    event.stopPropagation(); // 阻止事件冒泡
});

6.2 常用事件

// 鼠标事件
click: 点击
dblclick: 双击
mouseover: 鼠标悬停
mouseout: 鼠标离开
mousedown: 鼠标按下
mouseup: 鼠标释放
mousemove: 鼠标移动

// 键盘事件
keydown: 键盘按下
keyup: 键盘释放
keypress: 键盘按下并释放

// 表单事件
submit: 表单提交
change: 表单元素值改变
input: 表单元素输入
focus: 获得焦点
blur: 失去焦点

// 窗口事件
load: 页面加载完成
resize: 窗口大小改变
scroll: 页面滚动
hashchange: URL 哈希改变

// 触摸事件
touchstart: 触摸开始
touchmove: 触摸移动
touchend: 触摸结束

实例:事件处理

0

7. 异步编程

7.1 回调函数

// 回调函数示例
function fetchData(callback) {
    setTimeout(function() {
        const data = { name: "张三", age: 25 };
        callback(data);
    }, 1000);
}

// 使用回调函数
fetchData(function(data) {
    console.log("获取到数据:", data);
});

// 回调地狱
function step1(callback) {
    setTimeout(function() {
        console.log("步骤 1 完成");
        callback();
    }, 1000);
}

function step2(callback) {
    setTimeout(function() {
        console.log("步骤 2 完成");
        callback();
    }, 1000);
}

function step3(callback) {
    setTimeout(function() {
        console.log("步骤 3 完成");
        callback();
    }, 1000);
}

// 回调地狱
step1(function() {
    step2(function() {
        step3(function() {
            console.log("所有步骤完成");
        });
    });
});

7.2 Promise

// 创建 Promise
const promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
        const success = true;
        if (success) {
            resolve({ name: "张三", age: 25 });
        } else {
            reject("获取数据失败");
        }
    }, 1000);
});

// 使用 Promise
promise
    .then(function(data) {
        console.log("获取到数据:", data);
        return data.name;
    })
    .then(function(name) {
        console.log("姓名:", name);
    })
    .catch(function(error) {
        console.error("错误:", error);
    })
    .finally(function() {
        console.log("无论成功失败都会执行");
    });

// Promise 方法
Promise.all([promise1, promise2, promise3])
    .then(function(results) {
        console.log("所有 Promise 完成:", results);
    });

Promise.race([promise1, promise2, promise3])
    .then(function(result) {
        console.log("第一个完成的 Promise:", result);
    });

7.3 async/await(ES8+)

// async 函数
async function fetchData() {
    try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        return data;
    } catch (error) {
        console.error("错误:", error);
        throw error;
    }
}

// 使用 async/await
async function main() {
    try {
        const data = await fetchData();
        console.log("获取到数据:", data);
    } catch (error) {
        console.error("处理错误:", error);
    }
}

main();

实例:异步编程

8. ES6+ 特性

8.1 模板字符串

// 模板字符串
const name = "张三";
const age = 25;
const message = `Hello, my name is ${name} and I am ${age} years old.`;
console.log(message); // "Hello, my name is 张三 and I am 25 years old."

// 多行字符串
const multiLine = `
    第一行
    第二行
    第三行
`;
console.log(multiLine);

8.2 解构赋值

// 对象解构
const person = { name: "张三", age: 25, address: "北京" };
const { name, age } = person;
console.log(name, age); // "张三" 25

// 数组解构
const arr = [1, 2, 3, 4, 5];
const [first, second, ...rest] = arr;
console.log(first, second, rest); // 1 2 [3, 4, 5]

// 函数参数解构
function greet({ name, age }) {
    return `Hello, ${name}! You are ${age} years old.`;
}

const person2 = { name: "李四", age: 30 };
console.log(greet(person2)); // "Hello, 李四! You are 30 years old."

8.3 展开运算符

// 数组展开
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]

// 对象展开
const person = { name: "张三", age: 25 };
const personWithAddress = { ...person, address: "北京" };

// 函数参数展开
function sum(...numbers) {
    return numbers.reduce((total, num) => total + num, 0);
}

console.log(sum(1, 2, 3, 4, 5)); // 15

8.4 箭头函数

// 箭头函数
const add = (a, b) => a + b;
console.log(add(1, 2)); // 3

// 带函数体的箭头函数
const multiply = (a, b) => {
    return a * b;
};

// 单个参数可以省略括号
const square = x => x * x;

// 没有参数
const greet = () => "Hello!";

// 箭头函数中的 this
const person = {
    name: "张三",
    greet: function() {
        setTimeout(() => {
            console.log(`Hello, my name is ${this.name}`); // this 指向 person 对象
        }, 1000);
    }
};

person.greet(); // "Hello, my name is 张三"

8.5 模块化

// 导出模块(export.js)
export const name = "张三";
export function greet() {
    return "Hello!";
}

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

// 导入模块(import.js)
import add, { name, greet } from './export.js';

console.log(name); // "张三"
console.log(greet()); // "Hello!"
console.log(add(1, 2)); // 3

实例:ES6+ 特性

9. 错误处理

9.1 try...catch 语句

try {
    // 可能出错的代码
    const result = 10 / 0;
    console.log(result);
} catch (error) {
    // 处理错误
    console.error("错误:", error);
} finally {
    // 无论是否出错都会执行
    console.log("执行完毕");
}

// 示例
function divide(a, b) {
    if (b === 0) {
        throw new Error("除数不能为0");
    }
    return a / b;
}

try {
    const result = divide(10, 0);
    console.log(result);
} catch (error) {
    console.error("错误:", error.message);
}

9.2 自定义错误

class CustomError extends Error {
    constructor(message) {
        super(message);
        this.name = "CustomError";
    }
}

try {
    throw new CustomError("自定义错误");
} catch (error) {
    console.error(error.name + ": " + error.message);
}

实例:错误处理

10. 本地存储

10.1 localStorage

// 存储数据
localStorage.setItem("name", "张三");
localStorage.setItem("age", "25");

// 获取数据
const name = localStorage.getItem("name");
const age = localStorage.getItem("age");

// 删除数据
localStorage.removeItem("age");

// 清空所有数据
localStorage.clear();

// 存储对象
const person = { name: "张三", age: 25 };
localStorage.setItem("person", JSON.stringify(person));

// 获取对象
const storedPerson = JSON.parse(localStorage.getItem("person"));

10.2 sessionStorage

// 存储数据
sessionStorage.setItem("name", "张三");

// 获取数据
const name = sessionStorage.getItem("name");

// 删除数据
sessionStorage.removeItem("name");

// 清空所有数据
sessionStorage.clear();

实例:本地存储

11. 综合实例

11.1 待办事项列表

待办事项列表

12. 总结

本指南涵盖了 JavaScript 的核心概念和特性,包括:

通过本指南的学习,您应该能够掌握 JavaScript 的基本语法和常用功能,为前端开发打下坚实的基础。

继续练习和探索 JavaScript 的更多特性,您将能够开发出更加复杂和功能丰富的 Web 应用。