JavaScript学习大纲

由于篇幅限制,我将简要概述每个部分的关键点,而不是详细讲解每一个知识点。如果你需要更详细的解释,可以针对每个部分提出具体问题。

1. 基础概念

  • JavaScript 简介
    • JavaScript 是一种脚本语言,用于创建动态和交互式的网页。
    • 它可以在浏览器中运行,也可以在服务器端(Node.js)运行。
  • 开发环境
    • 浏览器开发工具(如 Chrome DevTools)可以帮助调试和分析代码。
    • 文本编辑器(如 VSCode)或 IDE(如 WebStorm)用于编写代码。

2. 基本语法

2.1 变量和数据类型

2.1.1 变量声明
  • var:

    • var 是 JavaScript 最早的变量声明方式,存在变量提升现象。
    • 范例:
      1
      2
      var x = 10;
      console.log(x); // 输出: 10
  • let:

    • let 是 ES6 引入的,用于声明块级作用域的变量。
    • 范例:
      1
      2
      let y = 20;
      console.log(y); // 输出: 20
  • const:

    • const 用于声明常量,一旦赋值就不能再更改。
    • 范例:
      1
      2
      3
      const z = 30;
      console.log(z); // 输出: 30
      // z = 40; // 会抛出 TypeError: Assignment to constant variable.
2.1.2 数据类型
  • 基本数据类型:

    • 字符串: 用于表示文本数据。
      1
      let str = "Hello, World!";
    • 数字: 用于表示整数和浮点数。
      1
      let num = 42;
    • 布尔值: truefalse
      1
      let isTrue = true;
    • null: 表示空值。
      1
      let emptyValue = null;
    • undefined: 表示未定义的值。
      1
      let undefinedValue;
    • Symbol: 唯一且不可变的值,通常用于对象属性。
      1
      let sym = Symbol('unique');
    • BigInt: 用于表示大整数。
      1
      let bigInt = 1234567890123456789012345678901234567890n;
  • 引用数据类型:

    • 对象: 用于存储键值对。
      1
      let obj = { name: "Alice", age: 25 };
    • 数组: 有序集合。
      1
      let arr = [1, 2, 3, 4, 5];

2.2 运算符

2.2.1 算术运算符
  • 加法(+:
    1
    let sum = 5 + 3; // 8
  • 减法(-:
    1
    let difference = 5 - 3; // 2
  • 乘法(*:
    1
    let product = 5 * 3; // 15
  • 除法(/:
    1
    let quotient = 5 / 3; // 1.6667
  • 取模(%:
    1
    let remainder = 5 % 3; // 2
  • 指数(**:
    1
    let power = 5 ** 3; // 125
2.2.2 赋值运算符
  • 赋值(=:
    1
    let x = 10;
  • 复合赋值运算符(如 +=, -=, *=, /=, %=):
    1
    2
    let y = 5;
    y += 3; // 等同于 y = y + 3; y 现在是 8
2.2.3 比较运算符
  • 等于(==)和全等于(===:
    1
    2
    5 == '5';  // true, 因为类型转换
    5 === '5'; // false, 因为不进行类型转换
  • 不等于(!=)和全不等于(!==:
    1
    2
    5 != '5';  // false, 因为类型转换后相等
    5 !== '5'; // true, 因为类型不同
  • 大于(>),小于(<),大于等于(>=),小于等于(<=
    1
    2
    5 > 3;  // true
    5 < 3; // false
2.2.4 逻辑运算符
  • 逻辑与(&&:
    1
    true && false; // false
  • 逻辑或(||:
    1
    true || false; // true
  • 逻辑非(!:
    1
    !true; // false
2.2.5 一元运算符和二元运算符
  • 一元运算符: 只操作一个操作数。
    1
    2
    let a = 1;
    a++; // 自增运算符,相当于 a = a + 1
  • 二元运算符: 操作两个操作数。
    1
    let b = 1 + 2; // 二元加法运算符

2.3 控制流

2.3.1 条件语句
  • if, else if, else:
    1
    2
    3
    4
    5
    6
    7
    8
    let num = 10;
    if (num > 10) {
    console.log('num 大于 10');
    } else if (num === 10) {
    console.log('num 等于 10');
    } else {
    console.log('num 小于 10');
    }
  • switch:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    let color = 'red';
    switch (color) {
    case 'red':
    console.log('The color is red');
    break;
    case 'blue':
    console.log('The color is blue');
    break;
    default:
    console.log('The color is not red or blue');
    }
2.3.2 循环语句
  • for:
    1
    2
    3
    for (let i = 0; i < 5; i++) {
    console.log(i); // 输出 0, 1, 2, 3, 4
    }
  • while:
    1
    2
    3
    4
    5
    let i = 0;
    while (i < 5) {
    console.log(i); // 输出 0, 1, 2, 3, 4
    i++;
    }
  • do...while:
    1
    2
    3
    4
    5
    let i = 0;
    do {
    console.log(i); // 输出 0, 1, 2, 3, 4
    i++;
    } while (i < 5);
2.3.3 跳转语句
  • break: 立即退出循环或 switch 语句。
    1
    2
    3
    4
    5
    6
    for (let i = 0; i < 5; i++) {
    if (i === 3) {
    break; // 退出循环
    }
    console.log(i); // 输出 0, 1, 2
    }
  • continue: 跳过当前循环的剩余部分,继续下一次循环。
    1
    2
    3
    4
    5
    6
    for (let i = 0; i < 5; i++) {
    if (i === 3) {
    continue; // 跳过当前循环
    }
    console.log(i); // 输出 0, 1, 2, 4
    }

3. 函数

3.1 函数声明和表达式

3.1.1 函数声明
  • 语法:
    1
    2
    3
    function functionName(parameters) {
    // 函数体
    }
  • 示例:
    1
    2
    3
    4
    5
    function add(a, b) {
    return a + b;
    }
    let result = add(2, 3); // 5
    console.log(result);
3.1.2 函数表达式
  • 语法:
    1
    2
    3
    const functionName = function(parameters) {
    // 函数体
    };
  • 示例:
    1
    2
    3
    4
    5
    const multiply = function(a, b) {
    return a * b;
    };
    let product = multiply(2, 3); // 6
    console.log(product);
3.1.3 匿名函数
  • 语法:
    1
    2
    3
    const anonymousFunction = function() {
    // 函数体
    };
  • 示例:
    1
    2
    3
    4
    const greet = function() {
    console.log('Hello, World!');
    };
    greet();

3.2 高级函数概念

3.2.1 默认参数
  • 语法:
    1
    2
    3
    function functionName(param1 = defaultValue1, param2 = defaultValue2) {
    // 函数体
    }
  • 示例:
    1
    2
    3
    4
    5
    function greet(name = 'Guest') {
    console.log('Hello, ' + name);
    }
    greet(); // Hello, Guest
    greet('Alice'); // Hello, Alice
3.2.2 箭头函数
  • 语法:
    1
    2
    3
    const functionName = (parameters) => {
    // 函数体
    };
  • 示例:
    1
    2
    const add = (a, b) => a + b;
    console.log(add(2, 3)); // 5
3.2.3 高阶函数
  • 高阶函数: 接受一个或多个函数作为参数,或者返回一个函数。
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function higherOrderFunction(callback) {
    callback();
    }

    function sayHello() {
    console.log('Hello!');
    }

    higherOrderFunction(sayHello); // Hello!
3.2.4 闭包
  • 闭包: 函数和其词法环境的组合,使得函数可以访问其作用域外的变量。
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function outerFunction() {
    let outerVariable = 'I am outside!';

    function innerFunction() {
    console.log(outerVariable);
    }

    return innerFunction;
    }

    const closure = outerFunction();
    closure(); // I am outside!
3.2.5 即时调用函数表达式 (IIFE)
  • 语法:
    1
    2
    3
    (function() {
    // 函数体
    })();
  • 示例:
    1
    2
    3
    (function() {
    console.log('IIFE executed');
    })();

3.3 函数参数和返回值

3.3.1 参数
  • 基本参数:
    1
    2
    3
    4
    function add(a, b) {
    return a + b;
    }
    console.log(add(2, 3)); // 5
  • 剩余参数: 用于传递不定数量的参数。
    1
    2
    3
    4
    function sum(...args) {
    return args.reduce((acc, val) => acc + val, 0);
    }
    console.log(sum(1, 2, 3, 4)); // 10
3.3.2 返回值
  • 基本返回值:
    1
    2
    3
    4
    function multiply(a, b) {
    return a * b;
    }
    console.log(multiply(2, 3)); // 6
  • 多个返回值: 可以使用数组或对象返回多个值。
    1
    2
    3
    4
    5
    function getCoordinates() {
    return { x: 10, y: 20 };
    }
    const coordinates = getCoordinates();
    console.log(coordinates.x, coordinates.y); // 10 20

3.4 函数作用域和上下文

3.4.1 作用域
  • 局部作用域: 在函数内声明的变量只能在函数内访问。
    1
    2
    3
    4
    5
    6
    function localScope() {
    let localVar = 'I am local';
    console.log(localVar);
    }
    localScope(); // I am local
    // console.log(localVar); // Uncaught ReferenceError: localVar is not defined
  • 全局作用域: 在函数外声明的变量可以在整个程序中访问。
    1
    2
    3
    4
    5
    let globalVar = 'I am global';
    function accessGlobalVar() {
    console.log(globalVar);
    }
    accessGlobalVar(); // I am global
3.4.2 上下文(this 关键字)
  • 全局上下文: this 指向全局对象(浏览器中是 window)。
    1
    console.log(this); // Window
  • 函数上下文: 在函数内 this 指向调用该函数的对象。
    1
    2
    3
    4
    5
    6
    7
    const obj = {
    value: 42,
    getValue: function() {
    return this.value;
    }
    };
    console.log(obj.getValue()); // 42

3.5 函数的其他高级用法

3.5.1 函数柯里化(Currying)
  • 函数柯里化: 将接受多个参数的函数转换为接受一个参数的函数,并返回一个新的函数。
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    function curryFunction(a) {
    return function(b) {
    return a + b;
    };
    }
    const addFive = curryFunction(5);
    console.log(addFive(3)); // 8
3.5.2 函数组合(Function Composition)
  • 函数组合: 将多个函数组合成一个新的函数,每个函数的输出作为下一个函数的输入。
  • 示例:
    1
    2
    3
    4
    5
    const compose = (f, g) => (x) => f(g(x));
    const addOne = (num) => num + 1;
    const double = (num) => num * 2;
    const addOneAndDouble = compose(double, addOne);
    console.log(addOneAndDouble(5)); // 12

3.6 函数式编程(Functional Programming)

  • 纯函数: 不依赖外部状态且不改变外部状态的函数。
  • 高阶函数: 接受函数作为参数或返回函数的函数。
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    const pureAdd = (a, b) => a + b;
    const map = (arr, fn) => {
    let result = [];
    for (let i = 0; i < arr.length; i++) {
    result.push(fn(arr[i]));
    }
    return result;
    };
    const numbers = [1, 2, 3, 4];
    const doubledNumbers = map(numbers, (num) => num * 2);
    console.log(doubledNumbers); // [2, 4, 6, 8]

4. 对象和数组

4.1 对象

4.1.1 对象的创建
  • 对象字面量:
    1
    2
    3
    4
    5
    6
    7
    const person = {
    name: 'Alice',
    age: 25,
    greet: function() {
    console.log('Hello, ' + this.name);
    }
    };
  • 构造函数:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function Person(name, age) {
    this.name = name;
    this.age = age;
    }

    Person.prototype.greet = function() {
    console.log('Hello, ' + this.name);
    };

    const bob = new Person('Bob', 30);
    bob.greet(); // Hello, Bob
  • Object.create 方法:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    const proto = {
    greet: function() {
    console.log('Hello, ' + this.name);
    }
    };

    const charlie = Object.create(proto);
    charlie.name = 'Charlie';
    charlie.greet(); // Hello, Charlie
4.1.2 对象的属性访问和操作
  • 访问属性:
    1
    2
    console.log(person.name); // Alice
    console.log(person['age']); // 25
  • 添加属性:
    1
    2
    person.job = 'Engineer';
    console.log(person.job); // Engineer
  • 删除属性:
    1
    2
    delete person.age;
    console.log(person.age); // undefined
  • 检查属性:
    1
    2
    console.log('name' in person); // true
    console.log(person.hasOwnProperty('age')); // false
4.1.3 对象方法
  • 基本方法:
    1
    2
    3
    4
    5
    6
    7
    const person = {
    name: 'Alice',
    greet: function() {
    console.log('Hello, ' + this.name);
    }
    };
    person.greet(); // Hello, Alice
  • ES6 简写方法:
    1
    2
    3
    4
    5
    6
    7
    const person = {
    name: 'Alice',
    greet() {
    console.log('Hello, ' + this.name);
    }
    };
    person.greet(); // Hello, Alice
4.1.4 对象的遍历
  • for...in 循环:
    1
    2
    3
    4
    5
    for (let key in person) {
    if (person.hasOwnProperty(key)) {
    console.log(key + ': ' + person[key]);
    }
    }
  • Object.keys 方法:
    1
    2
    3
    4
    const keys = Object.keys(person);
    keys.forEach(key => {
    console.log(key + ': ' + person[key]);
    });
  • Object.values 方法:
    1
    2
    3
    4
    const values = Object.values(person);
    values.forEach(value => {
    console.log(value);
    });
  • Object.entries 方法:
    1
    2
    3
    4
    const entries = Object.entries(person);
    entries.forEach(([key, value]) => {
    console.log(key + ': ' + value);
    });

4.2 数组

4.2.1 数组的创建
  • 数组字面量:
    1
    const numbers = [1, 2, 3, 4, 5];
  • 构造函数:
    1
    const fruits = new Array('Apple', 'Banana', 'Cherry');
  • Array.of 方法:
    1
    const letters = Array.of('a', 'b', 'c');
  • Array.from 方法:
    1
    2
    const str = 'hello';
    const strArray = Array.from(str); // ['h', 'e', 'l', 'l', 'o']
4.2.2 数组的操作
  • 访问元素:
    1
    console.log(numbers[0]); // 1
  • 修改元素:
    1
    2
    numbers[1] = 10;
    console.log(numbers); // [1, 10, 3, 4, 5]
  • 添加元素:
    1
    2
    numbers.push(6);
    console.log(numbers); // [1, 10, 3, 4, 5, 6]
  • 删除元素:
    1
    2
    numbers.pop();
    console.log(numbers); // [1, 10, 3, 4, 5]
4.2.3 数组的方法
  • pushpop:
    1
    2
    3
    4
    5
    6
    const stack = [];
    stack.push(1);
    stack.push(2);
    console.log(stack); // [1, 2]
    stack.pop();
    console.log(stack); // [1]
  • shiftunshift:
    1
    2
    3
    4
    5
    6
    const queue = [];
    queue.push(1);
    queue.push(2);
    console.log(queue); // [1, 2]
    queue.shift();
    console.log(queue); // [2]
  • slicesplice:
    1
    2
    3
    4
    5
    6
    const arr = [1, 2, 3, 4, 5];
    const sliced = arr.slice(1, 3);
    console.log(sliced); // [2, 3]

    arr.splice(1, 2);
    console.log(arr); // [1, 4, 5]
  • concatjoin:
    1
    2
    3
    4
    5
    6
    7
    const arr1 = [1, 2];
    const arr2 = [3, 4];
    const combined = arr1.concat(arr2);
    console.log(combined); // [1, 2, 3, 4]

    const joined = combined.join('-');
    console.log(joined); // "1-2-3-4"
4.2.4 数组的遍历
  • for 循环:
    1
    2
    3
    for (let i = 0; i < numbers.length; i++) {
    console.log(numbers[i]);
    }
  • for...of 循环:
    1
    2
    3
    for (let number of numbers) {
    console.log(number);
    }
  • forEach 方法:
    1
    2
    3
    numbers.forEach(number => {
    console.log(number);
    });
4.2.5 数组的高级方法
  • map: 创建一个新数组,包含原数组中每个元素调用提供的函数后的结果。
    1
    2
    const doubled = numbers.map(num => num * 2);
    console.log(doubled); // [2, 20, 6, 8, 10]
  • filter: 创建一个新数组,包含所有通过提供的函数实现的测试的元素。
    1
    2
    const evens = numbers.filter(num => num % 2 === 0);
    console.log(evens); // [10, 4]
  • reduce: 对数组中的每个元素执行一个提供的函数,将其结果汇总为单个值。
    1
    2
    const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
    console.log(sum); // 23
  • find: 返回数组中满足提供的测试函数的第一个元素的值。
    1
    2
    const firstEven = numbers.find(num => num % 2 === 0);
    console.log(firstEven); // 10
  • someevery:
    1
    2
    3
    4
    5
    const hasEven = numbers.some(num => num % 2 === 0);
    console.log(hasEven); // true

    const allEven = numbers.every(num => num % 2 === 0);
    console.log(allEven); // false

4.3 数组和对象的组合使用

  • 对象数组:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    const people = [
    { name: 'Alice', age: 25 },
    { name: 'Bob', age: 30 },
    { name: 'Charlie', age: 35 }
    ];

    people.forEach(person => {
    console.log(person.name + ' is ' + person.age + ' years old');
    });
  • 数组对象:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    const group = {
    members: ['Alice', 'Bob', 'Charlie'],
    addMember(name) {
    this.members.push(name);
    }
    };

    group.addMember('Dave');
    console.log(group.members); // ['Alice', 'Bob', 'Charlie', 'Dave']

5. 面向对象编程 (OOP)

5.1 基本概念

5.1.1 类和实例
  • : 类是创建对象的蓝图,它定义了对象的属性和方法。
  • 实例: 通过类创建的对象称为实例。
5.1.2 构造函数
  • 构造函数: 用于初始化类的新实例。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Person {
    constructor(name, age) {
    this.name = name;
    this.age = age;
    }

    greet() {
    console.log(`Hello, my name is ${this.name}`);
    }
    }

    const alice = new Person('Alice', 25);
    alice.greet(); // Hello, my name is Alice

5.2 继承

5.2.1 基本继承
  • extends 关键字: 用于创建一个类,该类是另一个类的子类。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Employee extends Person {
    constructor(name, age, jobTitle) {
    super(name, age);
    this.jobTitle = jobTitle;
    }

    work() {
    console.log(`${this.name} is working as a ${this.jobTitle}`);
    }
    }

    const bob = new Employee('Bob', 30, 'Developer');
    bob.greet(); // Hello, my name is Bob
    bob.work(); // Bob is working as a Developer
5.2.2 方法重写
  • 子类可以重写父类的方法,以提供特定的实现。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Employee extends Person {
    constructor(name, age, jobTitle) {
    super(name, age);
    this.jobTitle = jobTitle;
    }

    greet() {
    console.log(`Hi, I am ${this.name} and I work as a ${this.jobTitle}`);
    }
    }

    const bob = new Employee('Bob', 30, 'Developer');
    bob.greet(); // Hi, I am Bob and I work as a Developer

5.3 封装

5.3.1 公有和私有属性
  • 公有属性: 可以在类的外部访问。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Person {
    constructor(name, age) {
    this.name = name; // 公有属性
    this.age = age; // 公有属性
    }
    }

    const charlie = new Person('Charlie', 35);
    console.log(charlie.name); // Charlie
  • 私有属性: 只能在类的内部访问(ES6 中可以使用 # 来声明私有属性)。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Person {
    #privateAge; // 私有属性

    constructor(name, age) {
    this.name = name;
    this.#privateAge = age;
    }

    getAge() {
    return this.#privateAge;
    }
    }

    const charlie = new Person('Charlie', 35);
    console.log(charlie.getAge()); // 35
    // console.log(charlie.#privateAge); // Uncaught SyntaxError: Private field '#privateAge' must be declared in an enclosing class
5.3.2 Getter 和 Setter
  • Getter: 用于获取属性值的方法。
  • Setter: 用于设置属性值的方法。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    class Person {
    #age;

    constructor(name, age) {
    this.name = name;
    this.#age = age;
    }

    get age() {
    return this.#age;
    }

    set age(newAge) {
    if (newAge > 0) {
    this.#age = newAge;
    } else {
    console.log('Age must be positive');
    }
    }
    }

    const dave = new Person('Dave', 40);
    console.log(dave.age); // 40
    dave.age = 45;
    console.log(dave.age); // 45
    dave.age = -5; // Age must be positive

5.4 多态

5.4.1 方法重载
  • JavaScript 不支持方法重载,但可以通过检查参数来实现类似的效果。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Calculator {
    add(a, b) {
    if (typeof a === 'number' && typeof b === 'number') {
    return a + b;
    } else if (Array.isArray(a) && a.length && b === undefined) {
    return a.reduce((acc, val) => acc + val, 0);
    }
    return null;
    }
    }

    const calc = new Calculator();
    console.log(calc.add(2, 3)); // 5
    console.log(calc.add([1, 2, 3, 4])); // 10
5.4.2 接口和抽象类
  • JavaScript 没有内建的接口和抽象类,但可以通过设计模式实现类似的功能。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    class Animal {
    makeSound() {
    throw new Error('This method must be implemented by subclass');
    }
    }

    class Dog extends Animal {
    makeSound() {
    console.log('Woof Woof!');
    }
    }

    class Cat extends Animal {
    makeSound() {
    console.log('Meow Meow!');
    }
    }

    const dog = new Dog();
    dog.makeSound(); // Woof Woof!

    const cat = new Cat();
    cat.makeSound(); // Meow Meow!

5.5 原型和继承

5.5.1 原型链
  • 每个对象都有一个原型,对象可以从其原型继承属性和方法。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function Person(name, age) {
    this.name = name;
    this.age = age;
    }

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

    const emily = new Person('Emily', 28);
    emily.greet(); // Hello, my name is Emily
5.5.2 Object.create 方法
  • 使用 Object.create 方法可以设置一个对象的原型。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    const personPrototype = {
    greet() {
    console.log(`Hello, my name is ${this.name}`);
    }
    };

    const frank = Object.create(personPrototype);
    frank.name = 'Frank';
    frank.greet(); // Hello, my name is Frank
5.5.3 原型继承
  • 可以通过原型继承实现继承关系。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    function Animal(name) {
    this.name = name;
    }

    Animal.prototype.makeSound = function() {
    console.log('Some generic sound');
    };

    function Dog(name, breed) {
    Animal.call(this, name);
    this.breed = breed;
    }

    Dog.prototype = Object.create(Animal.prototype);
    Dog.prototype.constructor = Dog;

    Dog.prototype.makeSound = function() {
    console.log('Woof Woof!');
    };

    const rex = new Dog('Rex', 'Labrador');
    rex.makeSound(); // Woof Woof!

5.6 其他高级特性

5.6.1 静态方法
  • 静态方法是属于类而不是实例的方法。
    1
    2
    3
    4
    5
    6
    7
    class MathUtils {
    static add(a, b) {
    return a + b;
    }
    }

    console.log(MathUtils.add(5, 3)); // 8
5.6.2 单例模式
  • 单例模式确保一个类只有一个实例。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Singleton {
    constructor() {
    if (!Singleton.instance) {
    Singleton.instance = this;
    }
    return Singleton.instance;
    }
    }

    const instance1 = new Singleton();
    const instance2 = new Singleton();

    console.log(instance1 === instance2); // true
5.6.3 混入
  • 混入(Mixin)是将一个对象的属性和方法拷贝到另一个对象。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    const canFly = {
    fly() {
    console.log('Flying!');
    }
    };

    const canSwim = {
    swim() {
    console.log('Swimming!');
    }
    };

    class Animal {
    constructor(name) {
    this.name = name;
    }
    }

    Object.assign(Animal.prototype, canFly, canSwim);

    const bird = new Animal('Bird');
    bird.fly(); // Flying!
    bird.swim(); // Swimming!

好的,下面我将详细讲解 JavaScript 中的异步编程,包括回调函数、Promise、async/await 以及事件循环等概念。

6. 异步编程

6.1 回调函数

6.1.1 基本概念
  • 回调函数: 作为参数传递给另一个函数,并在某个事件发生后被调用的函数。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function fetchData(callback) {
    setTimeout(() => {
    callback('Data fetched');
    }, 1000);
    }

    fetchData((data) => {
    console.log(data); // Data fetched
    });
6.1.2 回调地狱
  • 回调地狱: 多层嵌套的回调函数,导致代码难以阅读和维护。
    1
    2
    3
    4
    5
    6
    7
    fetchData1((data1) => {
    fetchData2(data1, (data2) => {
    fetchData3(data2, (data3) => {
    console.log(data3);
    });
    });
    });

6.2 Promise

6.2.1 基本概念
  • Promise: 表示一个异步操作的最终完成(或失败)及其结果值的对象。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function fetchData() {
    return new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve('Data fetched');
    }, 1000);
    });
    }

    fetchData().then((data) => {
    console.log(data); // Data fetched
    });
6.2.2 链式调用
  • 链式调用: 通过 .then 方法链式调用多个异步操作。
    1
    2
    3
    4
    5
    6
    fetchData1()
    .then((data1) => fetchData2(data1))
    .then((data2) => fetchData3(data2))
    .then((data3) => {
    console.log(data3);
    });
6.2.3 错误处理
  • 错误处理: 使用 .catch 方法捕获和处理错误。
    1
    2
    3
    4
    5
    6
    7
    fetchData()
    .then((data) => {
    console.log(data);
    })
    .catch((error) => {
    console.error(error);
    });

6.3 async/await

6.3.1 基本概念
  • async/await: 一种更简洁的异步编程语法,使得异步代码看起来像同步代码。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    async function fetchData() {
    return new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve('Data fetched');
    }, 1000);
    });
    }

    async function main() {
    const data = await fetchData();
    console.log(data); // Data fetched
    }

    main();
6.3.2 错误处理
  • 错误处理: 使用 try/catch 块捕获和处理错误。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    async function main() {
    try {
    const data = await fetchData();
    console.log(data);
    } catch (error) {
    console.error(error);
    }
    }

    main();
6.3.3 并行执行
  • 并行执行: 使用 Promise.all 并行执行多个异步操作。
    1
    2
    3
    4
    5
    6
    async function main() {
    const [data1, data2] = await Promise.all([fetchData1(), fetchData2()]);
    console.log(data1, data2);
    }

    main();

6.4 事件循环

6.4.1 基本概念
  • 事件循环: JavaScript 运行时环境(如浏览器和 Node.js)处理异步操作的机制。
    • 调用栈: 执行同步代码。
    • 任务队列: 存放异步回调函数。
    • 微任务队列: 存放 Promise 回调函数。
6.4.2 执行顺序
  • 执行顺序: 事件循环的执行顺序是先执行调用栈中的同步代码,然后执行微任务队列中的任务,最后执行任务队列中的任务。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    console.log('Start');

    setTimeout(() => {
    console.log('Timeout');
    }, 0);

    Promise.resolve().then(() => {
    console.log('Promise');
    });

    console.log('End');

    // 输出顺序: Start -> End -> Promise -> Timeout

6.5 高级异步模式

6.5.1 生成器 (Generators)
  • 生成器: 一种可以暂停和恢复执行的函数。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function* generateNumbers() {
    let i = 0;
    while (true) {
    yield i++;
    }
    }

    const generator = generateNumbers();
    console.log(generator.next().value); // 0
    console.log(generator.next().value); // 1
6.5.2 异步生成器
  • 异步生成器: 结合生成器和异步编程。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    async function* fetchData() {
    let page = 1;
    while (true) {
    const data = await fetch(`https://api.example.com/data?page=${page}`);
    yield data;
    page++;
    }
    }

    async function main() {
    const generator = fetchData();
    for await (const data of generator) {
    console.log(data);
    }
    }

    main();
6.5.3 异步迭代器
  • 异步迭代器: 用于迭代异步数据源。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    const asyncIterable = {
    [Symbol.asyncIterator]() {
    let i = 0;
    return {
    next() {
    if (i < 3) {
    return Promise.resolve({ value: i++, done: false });
    }
    return Promise.resolve({ done: true });
    }
    };
    }
    };

    (async function() {
    for await (const num of asyncIterable) {
    console.log(num);
    }
    })();

好的,下面我将详细讲解 JavaScript 在浏览器环境中的运行机制、DOM 操作、事件处理、Web API 以及性能优化等方面的内容。

7. 浏览器环境

7.1 浏览器运行机制

7.1.1 JavaScript 引擎
  • JavaScript 引擎: 浏览器中的 JavaScript 引擎(如 V8、SpiderMonkey、JavaScriptCore)负责解析和执行 JavaScript 代码。
    • V8: Chrome 和 Node.js 使用的引擎。
    • SpiderMonkey: Firefox 使用的引擎。
    • JavaScriptCore: Safari 使用的引擎。
7.1.2 渲染引擎
  • 渲染引擎: 负责将 HTML、CSS 和 JavaScript 转换为可视化的网页。
    • Blink: Chrome 和 Opera 使用的渲染引擎。
    • Gecko: Firefox 使用的渲染引擎。
    • WebKit: Safari 使用的渲染引擎。
7.1.3 事件循环
  • 事件循环: 浏览器中的事件循环负责处理异步事件,确保 JavaScript 代码的执行顺序。
    • 调用栈: 执行同步代码。
    • 任务队列: 存放异步回调函数。
    • 微任务队列: 存放 Promise 回调函数。

7.2 DOM 操作

7.2.1 基本概念
  • DOM (Document Object Model): 文档对象模型,是 HTML 和 XML 文档的编程接口。
    1
    2
    const element = document.getElementById('myElement');
    console.log(element.textContent);
7.2.2 选择元素
  • 选择元素: 使用各种方法选择 DOM 元素。
    1
    2
    3
    4
    5
    const elementById = document.getElementById('myId');
    const elementsByClass = document.getElementsByClassName('myClass');
    const elementsByTag = document.getElementsByTagName('div');
    const elementByQuery = document.querySelector('#myId');
    const elementsByQuery = document.querySelectorAll('.myClass');
7.2.3 修改元素
  • 修改元素: 修改 DOM 元素的内容和样式。
    1
    2
    3
    const element = document.getElementById('myElement');
    element.textContent = 'New Text';
    element.style.color = 'red';
7.2.4 创建和删除元素
  • 创建和删除元素: 动态创建和删除 DOM 元素。
    1
    2
    3
    4
    5
    6
    const newElement = document.createElement('div');
    newElement.textContent = 'New Element';
    document.body.appendChild(newElement);

    const oldElement = document.getElementById('oldElement');
    oldElement.parentNode.removeChild(oldElement);

7.3 事件处理

7.3.1 基本概念
  • 事件处理: 响应用户的交互操作(如点击、滚动、键盘输入等)。
    1
    2
    3
    4
    const button = document.getElementById('myButton');
    button.addEventListener('click', () => {
    console.log('Button clicked');
    });
7.3.2 事件传播
  • 事件传播: 事件在 DOM 树中的传播方式(捕获阶段、目标阶段、冒泡阶段)。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const parent = document.getElementById('parent');
    const child = document.getElementById('child');

    parent.addEventListener('click', () => {
    console.log('Parent clicked');
    }, true); // 捕获阶段

    child.addEventListener('click', () => {
    console.log('Child clicked');
    }); // 冒泡阶段
7.3.3 事件委托
  • 事件委托: 利用事件冒泡机制,将事件处理程序绑定到父元素,减少内存消耗。
    1
    2
    3
    4
    5
    6
    const list = document.getElementById('myList');
    list.addEventListener('click', (event) => {
    if (event.target.tagName === 'LI') {
    console.log('List item clicked');
    }
    });

7.4 Web API

7.4.1 定时器
  • 定时器: 使用 setTimeoutsetInterval 执行延迟或周期性任务。
    1
    2
    3
    4
    5
    6
    7
    setTimeout(() => {
    console.log('Timeout');
    }, 1000);

    setInterval(() => {
    console.log('Interval');
    }, 1000);
7.4.2 网络请求
  • 网络请求: 使用 fetchXMLHttpRequest 进行网络请求。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    fetch('https://api.example.com/data')
    .then(response => response.json())
    .then(data => {
    console.log(data);
    });

    const xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://api.example.com/data');
    xhr.onload = () => {
    if (xhr.status === 200) {
    console.log(JSON.parse(xhr.responseText));
    }
    };
    xhr.send();
7.4.3 存储
  • 存储: 使用 localStoragesessionStorage 进行数据存储。
    1
    2
    3
    4
    5
    6
    7
    localStorage.setItem('key', 'value');
    const value = localStorage.getItem('key');
    console.log(value); // value

    sessionStorage.setItem('key', 'value');
    const sessionValue = sessionStorage.getItem('key');
    console.log(sessionValue); // value

7.5 性能优化

7.5.1 减少重绘和回流
  • 重绘和回流: 减少 DOM 操作,使用 DocumentFragmentrequestAnimationFrame
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const fragment = document.createDocumentFragment();
    for (let i = 0; i < 10; i++) {
    const div = document.createElement('div');
    fragment.appendChild(div);
    }
    document.body.appendChild(fragment);

    function animate() {
    // 动画逻辑
    requestAnimationFrame(animate);
    }
    requestAnimationFrame(animate);
7.5.2 使用事件委托
  • 事件委托: 减少事件处理程序的数量,提高性能。
    1
    2
    3
    4
    5
    6
    const list = document.getElementById('myList');
    list.addEventListener('click', (event) => {
    if (event.target.tagName === 'LI') {
    console.log('List item clicked');
    }
    });
7.5.3 异步加载 JavaScript
  • 异步加载 JavaScript: 使用 asyncdefer 属性异步加载脚本。
    1
    2
    <script src="script.js" async></script>
    <script src="script.js" defer></script>
7.5.4 代码分割和懒加载
  • 代码分割和懒加载: 使用 Webpack 等工具进行代码分割,实现懒加载。
    1
    2
    3
    import('./module.js').then(module => {
    module.default();
    });

模块化是在现代JavaScript开发中非常重要的一个概念,主要是为了解决代码维护、命名空间、重用等问题。以下是模块化在JavaScript中的详细讲解。

8. 模块化

8.1 基本概念

8.1.1 模块的意义
  • 封装: 将代码封装成独立的单元,每个模块只负责一部分功能。
  • 命名空间: 每个模块提供自己的作用域,以避免全局命名冲突。
  • 重用性: 模块可被多处重用,减少代码重复。
  • 依赖管理: 模块化提供了一种清晰的方式来表达和管理依赖关系。

8.2 CommonJS 和 AMD

8.2.1 CommonJS
  • CommonJS: 主要用于服务器端,如Node.js,通过 require 来同步加载模块。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // math.js
    function add(a, b) {
    return a + b;
    }
    module.exports = { add };

    // app.js
    const math = require('./math');
    console.log(math.add(1, 2));
8.2.2 AMD (Asynchronous Module Definition)
  • AMD: 用于浏览器端的异步模块定义,代表性实现是 RequireJS
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 使用RequireJS
    define(['dependency'], function(dependency) {
    function myModuleFunction() {
    return dependency.someFunction();
    }
    return {
    myModuleFunction
    };
    });

8.3 ES6 模块

8.3.1 Export 和 Import
  • ES6 模块: 使用 export 关键字导出模块,使用 import 关键字导入模块。
    1
    2
    3
    4
    5
    6
    7
    8
    // math.js
    export function add(a, b) {
    return a + b;
    }

    // app.js
    import { add } from './math';
    console.log(add(1, 2));
8.3.2 默认导出和命名导出
  • 默认导出: 一个模块只能有一个默认导出。
    1
    2
    3
    4
    5
    6
    7
    8
    // math.js
    export default function add(a, b) {
    return a + b;
    }

    // app.js
    import add from './math';
    console.log(add(1, 2));
  • 命名导出: 一个模块可以有多个命名导出。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // math.js
    export function add(a, b) {
    return a + b;
    }
    export function subtract(a, b) {
    return a - b;
    }

    // app.js
    import { add, subtract } from './math';
    console.log(subtract(add(1, 2), 1));

8.4 模块加载机制

8.4.1 同步和异步加载
  • 同步加载: 模块在被导入时立即加载,常见于服务器端。
  • 异步加载: 模块在需要时才加载,适合大型应用,减少初始加载时间。

8.5 构建工具和模块打包

8.5.1 Webpack
  • Webpack: 模块打包器,可以将多个模块打包成一个或多个bundle,支持代码分割和懒加载。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // Webpack配置文件
    module.exports = {
    entry: './app.js',
    output: {
    filename: 'bundle.js'
    },
    module: {
    rules: [
    { test: /\.js$/, use: 'babel-loader' }
    ]
    }
    };
8.5.2 Babel
  • Babel: JavaScript编译器,可以将ES6+代码转换为向后兼容的JavaScript版本,以支持旧浏览器。
    1
    2
    3
    4
    // Babel配置
    {
    "presets": ["@babel/preset-env"]
    }
8.5.3 模块解析
  • 模块解析: 构建工具在打包时需要解析模块路径,处理模块的导入和导出。

8.6 模块化最佳实践

8.6.1 避免全局变量
  • 尽量不要在模块中定义全局变量,以避免污染全局命名空间。
8.6.2 高内聚低耦合
  • 高内聚: 模块内部功能紧密相关。
  • 低耦合: 模块之间依赖关系简单清晰。
8.6.3 导出和导入必要的内容
  • 只导出模块的公共接口,不要导出内部实现细节。
  • 只导入所需的功能,避免无用代码。

9. 错误处理与调试

  • 错误类型
    • JavaScript 有多种错误类型,包括语法错误、运行时错误和逻辑错误。
  • 错误处理
    • 使用 try, catch, finally 语句可以捕获和处理错误。
  • 调试技术
    • 使用浏览器开发工具和 console 对象可以帮助调试代码。

10. 高级主题

  • 正则表达式
    • 正则表达式用于匹配字符串中的模式。
  • 设计模式
    • 设计模式是解决常见问题的最佳实践。
  • 性能优化
    • 性能优化包括内存管理、代码优化和延迟加载等技术。

11. 实战项目

  • 项目设置
    • 项目结构和版本控制(如 Git)是项目开发的基础。
  • 前端框架
    • React、Vue.js 和 Angular 是流行的前端框架,用于构建复杂的用户界面。
  • 后端开发
    • Node.js 和 Express 是常用的后端开发技术。

12. 学习资源

  • 书籍推荐
    • 《JavaScript 高级程序设计》和《你不知道的 JavaScript》是深入学习 JavaScript 的好书。
  • 在线课程
    • Codeacademy、FreeCodeCamp 和 Udemy 提供了丰富的在线课程。
  • 社区与论坛
    • Stack Overflow、GitHub 和 Reddit 是获取帮助和分享知识的社区。