关于前端:现代JavaScript高级教程面向对象编程与Class

44次阅读

共计 5777 个字符,预计需要花费 15 分钟才能阅读完成。

点击在线浏览,体验更好 链接
古代 JavaScript 高级小册 链接
深入浅出 Dart 链接
古代 TypeScript 高级小册 链接

面向对象编程与 Class

引言

随着 JavaScript 的倒退,ECMAScript 6(ES6)引入了许多新的语言个性和语法糖,其中包含了面向对象编程的 Class(类)机制。Class 提供了一种更简洁、更直观的形式来定义对象和操作对象的行为。本文将介绍 ES6 中 Class 的概念、语法和个性,并通过示例代码来阐明其理论利用。

1. 什么是面向对象编程?

面向对象编程(Object-Oriented Programming,简称 OOP)是一种编程范式,它将程序中的对象作为根本单元,通过封装、继承和多态等机制来组织和治理代码。面向对象编程将事实世界中的实体形象为代码中的对象,对象领有本人的状态(属性)和行为(办法),并与其余对象进行交互。

面向对象编程有以下几个外围概念:

  • 封装(Encapsulation):将数据和操作数据的办法封装在一个对象中,使其成为一个独立的实体,内部无奈间接拜访对象的外部实现细节。
  • 继承(Inheritance):通过定义一个基类(父类),其余类能够继承该基类的属性和办法,并能够在此基础上进行扩大或笼罩。
  • 多态(Polymorphism):不同对象能够对雷同的办法做出不同的响应,即同一个办法能够依据调用对象的不同而具备不同的行为。

面向对象编程的劣势包含代码的可重用性、可维护性、扩展性和灵活性等。

2. Class 的基本概念

在 ES6 之前,JavaScript 中的对象和面向对象编程的概念绝对比拟含糊。ES6 引入了 Class 机制,使得 JavaScript 能够更加直观地定义和应用类。Class 是一种非凡的函数,通过 Class 关键字定义。Class 中能够定义构造函数、属性和办法等。

一个简略的 Class 示例如下:

class Rectangle {constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  area() {return this.width * this.height;}

  perimeter() {return 2 * (this.width + this.height);
  }
}

在上述示例中,咱们定义了一个名为 Rectangle 的类,

它具备 widthheight两个属性,以及 area()perimeter()两个办法。通过 Class 定义的类能够通过实例化来创立具体的对象,并调用其属性和办法。

const rect = new Rectangle(5, 3);
console.log(rect.area());       // 输入:15
console.log(rect.perimeter());  // 输入:16

3. Class 的语法

ES6 中 Class 的语法绝对简洁明了。一个 Class 能够蕴含构造函数、属性和办法等。上面介绍一些罕用的语法规定:

3.1 构造函数

在 Class 中应用 constructor 关键字定义构造函数。构造函数用于创建对象时进行初始化操作,通过 new 关键字实例化类时会主动调用构造函数。

class Rectangle {constructor(width, height) {
    this.width = width;
    this.height = height;
  }
}

构造函数中的 this 关键字示意以后实例化的对象。

3.2 属性

在 Class 中能够定义各种属性。属性能够间接定义在 Class 的外部,也能够在构造函数中通过 this 关键字进行定义。

class Rectangle {
  width = 0;    // 间接定义属性
  height = 0;

  constructor(width, height) {
    this.width = width;    // 在构造函数中定义属性
    this.height = height;
  }
}

3.3 办法

在 Class 中定义的函数称为办法。能够间接在 Class 的外部定义方法,也能够应用 ES6 的简写模式。

class Rectangle {constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  area() {            // 定义方法
    return this.width * this.height;
  }

  perimeter() {return 2 * (this.width + this.height);
  }
}

3.4 办法的拜访修饰符

在 Class 中,能够应用拜访修饰符来限度办法的拜访权限。ES6 中的 Class 默认所有办法都是公共的,能够被内部调用。但咱们能够应用 staticgetsetprivateprotected等修饰符来管制办法的拜访。

  • static:定义静态方法,只能通过类自身调用,不能通过类的实例调用。
  • getset:定义属性的读取和设置办法,应用相似拜访属性的语法进行调用。
  • private:定义公有办法,只能在类的外部被拜访,内部无法访问。
  • protected:定义受爱护办法,只能在类的外部和子类中被拜访,内部无法访问。
class Rectangle {
  static description = 'This is a rectangle';  // 动态属性

  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  static createSquare(side) {     // 静态方法
    return new Rectangle(side, side);
  }



  get area() {           // Getter 办法
    return this.width * this.height;
  }

  set area(value) {     // Setter 办法
    this.width = Math.sqrt(value);
    this.height = Math.sqrt(value);
  }

  #privateMethod() {    // 公有办法
    console.log('This is a private method');
  }

  protectedMethod() {   // 受爱护办法
    console.log('This is a protected method');
  }

  publicMethod() {      // 公共办法
    console.log('This is a public method');
    this.#privateMethod();
    this.protectedMethod();}
}

在上述示例中,咱们定义了一个 Square 类,它继承自 Rectangle 类。通过 super 关键字调用父类的构造函数,确保父类的属性被正确初始化。子类能够新增或笼罩父类的办法。

const square = new Square(5);
console.log(square.area());       // 输入:25
console.log(square.perimeter());  // 输入:20

4. 类的静态方法和属性

静态方法和属性属于类自身,而不是类的实例。静态方法和属性能够通过类名间接拜访,无需实例化类。

class MathUtil {
  static PI = 3.14159;    // 动态属性

  static square(number) {    // 静态方法
    return number * number;
  }
}

在上述示例中,咱们定义了一个 MathUtil 类,它具备一个动态属性 PI 和一个静态方法square()。能够通过类名间接拜访动态属性和办法。

console.log(MathUtil.PI);        // 输入:3.14159
console.log(MathUtil.square(5)); // 输入:25

5. Getter 和 Setter 办法

Getter 和 Setter 办法用于对类的属性进行读取和设置操作,能够通过相似拜访属性的语法进行调用。

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

  get diameter() {return 2 * this.radius;}

  set diameter(value) {this.radius = value / 2;}
}

在上述示例中,咱们定义了一个 Circle 类,它具备一个属性 radius。通过定义get diameter() 办法和 set diameter() 办法,咱们能够通过相似拜访属性的形式来读取和设置直径(diameter)属性,而不须要间接拜访 radius 属性。

const circle = new Circle(5);
console.log(circle.diameter);     //

 输入:10
circle.diameter = 12;
console.log(circle.radius);       // 输入:6

6. 类的公有属性和办法

在 ES6 中,能够应用 # 作为前缀来定义公有属性和办法。公有属性和办法只能在类的外部被拜访,内部无法访问。

class Person {
  #name;   // 公有属性

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

  #privateMethod() {   // 公有办法
    console.log('This is a private method');
  }

  publicMethod() {      // 公共办法
    console.log(`Hello, my name is ${this.#name}`);
    this.#privateMethod();}
}

在上述示例中,咱们定义了一个 Person 类,它具备一个公有属性 #name 和一个公有办法#privateMethod()。公有属性和办法只能在类的外部拜访。

const person = new Person('John');
person.publicMethod();   // 输入:Hello, my name is John
person.#name;            // 报错:SyntaxError: Private field '#name' must be declared in an enclosing class
person.#privateMethod(); // 报错:SyntaxError: Private field '#privateMethod' must be declared in an enclosing class

7. 类的实例和构造函数

在 ES6 中,类的实例通过 new 关键字进行创立,并主动调用类的构造函数进行初始化。

const rect = new Rectangle(5, 3);
console.log(rect.area());       // 输入:15
console.log(rect.perimeter());  // 输入:16

能够应用 instanceof 运算符来判断一个对象是否是某个类的实例。

console.log(rect instanceof Rectangle);  // 输入:true
console.log(rect instanceof Object);     // 输入:true

8. 类的继承

继承是面向对象编程中的重要概念之一,它容许咱们创立一个基类(父类),其余类能够继承该基类并扩大或笼罩其中的属性和办法。ES6 中应用 extends 关键字实现类的继承。

class Square extends Rectangle {constructor(side) {super(side, side);    // 调用父类的构造函数
  }
}

9. 类的封装

封装通过将数据和操作数据的办法封装在一个对象中,实现了数据的爱护和拜访的管制。类的属性和办法能够应用不同的拜访修饰符来管制其可见性。

class Rectangle {
  #width;  // 公有属性
  #height;

  constructor(width, height) {
    this.#width = width;
    this.#height = height;
  }

  getArea() {    // 公共办法
    return this.#width * this.#height;
  }
}

const rect = new Rectangle(5, 3);
console.log(rect.#width);  // 报错:SyntaxError: Private field '#width' must be declared in an enclosing class
console.log(rect.getArea());  // 输入:15

在上述示例中,Rectangle 类具备公有属性 #width 和#height,只能在类的外部被拜访。通过定义公共办法 getArea()来拜访公有属性,从而实现了封装。

10. 类的多态

多态容许不同的对象对雷同的音讯作出不同的响应。通过继承和办法的笼罩,不同的子类能够对父类的办法进行不同的实现,从而实现多态性。

class Animal {makeSound() {console.log('Animal makes sound');
  }
}

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

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

const animal = new Animal();
const dog = new Dog();
const cat = new Cat();

animal.makeSound();  // 输入:Animal makes sound
dog.makeSound();     // 输入:Dog barks
cat.makeSound();     // 输入:Cat meows

在上述示例中,Animal 类是基类,Dog 和 Cat 类是子类。它们都具备 makeSound()办法,但不同的子类对该办法进行了不同的实现,实现了多态性。

通过封装、继承和多态,面向对象编程提供了一种更加灵便和可扩大的编程形式,使得代码的组织和治理更加直观和高效。

11. 结语

ES6 引入的 Class 机制为 JavaScript 提供了一种更直观、更简洁的面向对象编程形式。通过 Class,咱们能够更不便地定义和应用类,实现封装、继承和多态等面向对象编程的基本原理。同时,ES6 还提供了许多其余的语法糖和个性,使得 JavaScript 在面向对象编程方面更加弱小和灵便。

12. 参考资料

  • MDN Web Docs – Classes
  • ECMAScript 6 入门 – Class
  • Understanding ECMAScript 6 – Classes
  • Exploring ES6 – Classes

正文完
 0