Javascript 编程基础(5)面向对象 | 5.3、class 语法糖


前言:

JavaScript 的 class 语法是 ES6(2015)引入的语法糖,用于简化原型继承的写法,使代码更接近传统面向对象语言的风格。尽管语法上更像类,但它本质上仍是基于原型的继承机制

一、class 语法糖

1、基本语法

class Animal {
  // 构造函数(创建实例时自动调用)
  constructor(type) {
    this.type = type;
  }

  // 实例方法(自动添加到原型)
  speak() {
    console.log(`${this.type} makes a sound`);
  }

  // 静态方法(属于类本身,不被实例继承)
  static info() {
    console.log("This is an Animal class");
  }
}

// 创建实例
const cat = new Animal("Cat");
cat.speak(); // 输出: Cat makes a sound
Animal.info(); // 输出: This is an Animal class

2、核心特性

2.1、继承(extends

class Dog extends Animal {
  constructor(name) {
    super("Dog"); // 调用父类构造函数
    this.name = name;
  }

  // 子类方法
  bark() {
    super.speak(); // 调用父类方法
    console.log(`${this.name} barks!`);
  }
}

const dog = new Dog("Buddy");
dog.bark(); 
// 输出: 
// Dog makes a sound
// Buddy barks!

2.2、私有属性和方法(#

ES2022 引入的私有语法,通过 # 前缀标记:

class Person {
  #age = 0; // 私有属性

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

  #privateMethod() {
    console.log("This is private");
  }

  publicMethod() {
    this.#privateMethod(); // 内部可访问
  }
}

const p = new Person("Alice", 30);
console.log(p.#age); // 报错:无法访问私有属性
p.publicMethod(); // 正常调用

2.3、静态属性和方法

属于类本身,不被实例继承:

class Circle {
  static PI = 3.14; // 静态属性

  constructor(radius) {
    this.radius = radius;
  }

  static area(radius) { // 静态方法
    return this.PI * radius * radius;
  }
}

console.log(Circle.PI); // 3.14
console.log(Circle.area(5)); // 78.5

3、与传统原型的对比

特性class 语法传统原型
方法定义简洁的语法(speak() {...}需显式赋值到原型(Animal.prototype.speak = ...
继承extends 关键字自动设置原型链需手动设置 Child.prototype = Object.create(Parent.prototype)
私有成员支持 # 语法需通过闭包或 WeakMap 模拟
静态成员直接用 static 关键字需手动添加到构造函数(如 Animal.info = ...
严格模式类内部默认使用严格模式需要显式声明 "use strict";

4、本质仍是原型

尽管 class 语法更像类,但 JavaScript 仍是基于原型的语言。例如:

class MyClass {}
const obj = new MyClass();

// 验证原型关系
console.log(obj.__proto__ === MyClass.prototype); // true
console.log(MyClass.prototype.constructor === MyClass); // true

5、注意事项

在JavaScript中使用class语法时,虽然它简化了原型继承的写法,但仍有一些容易踩坑的细节需要注意。以下是常见的注意事项:

5.1、类不会被提升(Hoisting)

与函数声明不同,类必须先声明后使用

const cat = new Animal(); // 报错:Animal未定义

class Animal {}

而函数声明可以被提升:

const cat = new Animal(); // 正常运行

function Animal() {}

5.2、类方法不可枚举

类中定义的方法默认不可枚举(enumerable: false),而传统原型方法是可枚举的:

class Animal {
  speak() {}
}

function Dog() {}
Dog.prototype.bark = function() {};

console.log(Object.keys(Animal.prototype)); // []
console.log(Object.keys(Dog.prototype));    // ['bark']

5.3、必须使用new调用类构造函数

类构造函数必须通过new关键字调用,否则会报错:

class Animal {
  constructor() {}
}

Animal(); // 报错:Class constructor Animal cannot be invoked without 'new'

而普通函数可以直接调用:

function Animal() {}
Animal(); // 正常运行(但可能导致全局污染)

5.4、静态成员不被实例继承

静态属性和方法属于类本身,实例无法访问:

class Circle {
  static PI = 3.14;
  static area(r) { return this.PI * r * r; }
}

const c = new Circle();
console.log(c.PI);     // undefined
console.log(c.area(5)); // 报错:c.area is not a function

5.5、子类构造函数必须调用super()

在子类构造函数中,必须先调用super()才能使用this

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

class Dog extends Animal {
  constructor(name) {
    // 必须先调用super()
    super("Dog");
    this.name = name;
  }
}

5.6、类方法中的this可能丢失上下文**

类方法不会自动绑定this,可能导致上下文丢失:

class Button {
  constructor(text) {
    this.text = text;
  }

  click() {
    console.log(`Clicked: ${this.text}`);
  }
}

const btn = new Button("Submit");
const handler = btn.click;
handler(); // 报错:Cannot read property 'text' of undefined

解决方法

  • 在构造函数中绑定this
    constructor() {
      this.click = this.click.bind(this);
    }
    
  • 使用箭头函数(自动绑定this):
    click = () => {
      console.log(`Clicked: ${this.text}`);
    }
    

5.7、避免修改原生类的原型

修改内置类(如ArrayObject)的原型可能导致全局冲突:

// 不推荐
class MyArray extends Array {
  static customMethod() { /* ... */ }
}

// 更好的做法:封装而非继承
class Wrapper {
  constructor() {
    this.array = [];
  }
  add(item) { this.array.push(item); }
}

6、总结

JavaScript 的 class 语法通过更简洁、更符合直觉的方式实现继承,但并未改变其基于原型的本质。它提供了私有成员、静态成员、继承等现代语言特性,使代码更具可读性和可维护性,尤其适合大型项目和团队协作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值