JavaScript 类(class)

关键要点

  • JavaScript 类是创建对象的模板,基于原型,语法简洁。
  • 类有构造函数、方法、字段,可通过 extends 实现继承。
  • 私有属性用 # 符号,静态方法用 static 关键字。
  • 类始终在严格模式下,this 绑定与普通函数不同。

定义与使用

JavaScript 类用 class 关键字定义,包含构造函数和方法。例如:

class Person {
    constructor(name) {
        this.name = name;
    }
    sayHello() {
        return `Hello, ${this.name}`;
    }
}
const p = new Person("Alice");
console.log(p.sayHello()); // 输出 "Hello, Alice"

类支持继承,如 class Student extends Person,子类需用 super() 调用父类构造函数。

私有与静态

私有属性用 # 定义,仅类内访问;静态方法用 static 定义,属于类而非实例。例如:

class MyClass {
    #privateField = "secret";
    static staticMethod() {
        return "Static method called";
    }
}

注意事项

类在严格模式下运行,this 绑定需注意上下文。类声明受时间死区影响,必须先定义后使用。



详细报告

JavaScript 类(class)是 ECMAScript 2015(ES6)引入的语法糖,旨在提供更直观的面向对象编程方式。尽管 JavaScript 底层仍是基于原型的,但类提供了更接近传统面向对象语言(如 Java、C++)的语法。以下是关于 JavaScript 类的全面中文讲解。

什么是类?

类是创建对象的模板,用于封装数据和处理这些数据的方法。类基于原型(prototype)继承,但有独特的语法和语义。自 2016 年 3 月起,类成为 JavaScript 标准的一部分,浏览器支持度较高。

  • 特点:类是函数的语法糖,实际上仍是构造函数,但提供了更清晰的结构。
  • 用途:适合定义对象模板,管理状态和行为,如用户、商品等。

定义类的两种方式

有两种定义类的方式:

  1. 类声明(Class Declaration)
   class MyClass {
       // 类体
   }

类声明必须在定义前使用,受时间死区(Temporal Dead Zone, TDZ)限制。

  1. 类表达式(Class Expression)
   const MyClass = class {
       // 类体
   };

类表达式可以匿名或命名,灵活性更高。

类体的组成

类体用大括号 {} 包裹,包含以下元素:

  • 构造函数(Constructor):用于创建和初始化对象。每个类最多有一个构造函数,否则抛出 SyntaxError
  class Person {
      constructor(name, age) {
          this.name = name;
          this.age = age;
      }
  }
  • 方法(Methods):定义在原型上,实例共享。支持普通函数、异步函数(async)、生成器函数(function*)和异步生成器函数。
  class MyClass {
      myMethod() {
          return "Regular method";
      }
      async asyncMethod() {
          return await Promise.resolve("Async method");
      }
  }
  • 静态方法和字段(Static Methods and Fields):用 static 关键字定义,属于类本身而非实例,适合工具函数或固定数据。
  class MathUtil {
      static add(a, b) {
          return a + b;
      }
  }
  console.log(MathUtil.add(5, 3)); // 输出 8
  • 字段声明(Field Declaration):在类体中直接定义属性,可有默认值或为 undefined。这是 ES2022 引入的特性。
  class MyClass {
      myField = "default";
      anotherField; // 默认 undefined
  }
  • 私有属性(Private Properties):用 # 符号声明,仅类内部可访问,提供封装性。
  class MyClass {
      #privateField = "secret";
      getPrivate() {
          return this.#privateField;
      }
  }
  const obj = new MyClass();
  console.log(obj.getPrivate()); // 输出 "secret"
  console.log(obj.#privateField); // 错误:私有字段不可访问

继承与 extends

类支持继承,使用 extends 关键字。子类构造函数必须先调用 super(),以确保父类初始化完成。

class Animal {
    constructor(name) {
        this.name = name;
    }
    speak() {
        return `${this.name} makes a sound`;
    }
}

class Dog extends Animal {
    constructor(name) {
        super(name); // 调用父类构造函数
    }
    speak() {
        return `${this.name} barks`;
    }
}

const dog = new Dog("Rex");
console.log(dog.speak()); // 输出 "Rex barks"

类评估顺序

类的评估顺序包括以下步骤:

  1. 评估 extends 子句(如果有)。
  2. 评估构造函数。
  3. 评估属性键。
  4. 设置方法和存取器。
  5. 初始化字段和静态属性。
  6. 类准备好作为构造函数使用。

如果在类定义前访问类名,会抛出 ReferenceError

this 的绑定

类始终在严格模式下运行,this 的绑定与普通函数不同:

  • 在方法调用时,如果没有明确上下文,thisundefined,而非全局对象(如 window)。
  • 示例:
  class MyClass {
      method() {
          console.log(this);
      }
  }
  const obj = new MyClass();
  obj.method(); // 输出实例对象
  MyClass.method(); // 严格模式下抛错,this 为 undefined

最佳实践与注意事项

  • 严格模式:类始终在严格模式下运行,需注意 this 绑定和变量声明。
  • 时间死区:类声明和表达式受 TDZ 影响,必须先定义后使用。
  • 私有属性:使用 # 确保封装,避免外部直接访问。
  • 静态初始化块:ES2022 引入,支持灵活初始化静态属性。
  class MyClass {
      static {
          this.staticField = "Initialized";
      }
  }

表格:类元素总结

元素描述示例
构造函数初始化对象,子类需用 super() 调用父类constructor(name) { this.name = name; }
普通方法原型方法,实例共享sayHello() { return "Hello"; }
静态方法属于类,实例不可访问static add(a, b) { return a + b; }
字段类体中定义属性,可有默认值myField = "default";
私有属性# 声明,仅类内访问#privateField = "secret";
继承extends 实现,子类需调用 super()class Child extends Parent { ... }

总结

JavaScript 类提供了一种现代化的面向对象编程方式,支持构造函数、方法、字段、继承和私有属性。类基于原型,但语法更直观,适合构建复杂对象结构。需注意严格模式和时间死区的限制,使用时遵循最佳实践以提高代码可维护性。


关键引文

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注