一、什么是面向对象
JavaScript 的面向对象编程(OOP)是一种使用对象来管理代码的方式。JavaScript是一种基于原型(Prototype)的语言,但本质上还是面向对象。原型本身也是对象,可以包含属性和方法,以支持封装、继承和多态面向对象编程的核心理念。
二、具象和抽象的对比
字面量对象(面向对象的直接应用)
const person = {
name: "Alice",
age: 30,
greet: function() {
console.log("Hello, " + this.name);
}
};
person.greet(); // 输出 "Hello, Alice"
原型对象(JS底层的面向对象原理)
// 构造函数
function Person(name, age) {
this.name = name;
this.age = age;
}
// 在原型上添加 greet 方法
Person.prototype.greet = function() {
console.log("Hello, " + this.name);
};
// 创建一个实例
const alice = new Person("Alice", 30);
// 调用 greet 方法
alice.greet(); // 输出 "Hello, Alice"
三、原型和原型链
在JavaScript中,每个对象(除了null)都有一个被称为原型(prototype)的内部链接,这个链接指向它的原型对象。这个原型对象也可以是一个普通的对象,因此它自己也可能有一个原型。这样就形成了一个链式结构,即原型链(prototype chain)。
在JavaScript中,无论是通过字面量对象、函数构造器与this关键字,还是通过ES6引入的class语法糖,都可以创建原型。
通过原型和原型链,JavaScript 可以实现对象的继承、动态扩展和代码复用。
四、封装、继承和多态
一般来说,我们用es6新增的class语法糖(类)代替原型对象实现面向对象编程,以便更加直观地定义对象(封装),及实现子对象获取父对象的属性和方法(继承)和不同子对象用调用同一个父对象方法,实现不同效果(多态)。
封装
封装即创建对象。该对象中包含其属性和一些方法,当使用类创建对象时,需要通过new关键字创建实例。
class Person {
constructor(name, age) {
this.name = name; // 封装属性
this.age = age;
}
greet() {
console.log("Hello, " + this.name);
}
}
// 创建一个实例
const alice = new Person("Alice", 30);
// 调用 greet 方法
alice.greet() // 输出"Hello Alice"
继承
继承即子对象获取父对象的属性和方法,拿来自己使用。子类一般用super关键字调用父类的constructor方法继承属性,而父类的方法则通过extends自动继承。
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log("Hello, " + this.name);
}
}
// Student 类继承自 Person 类
class Student extends Person {
constructor(name, age, grade) {
super(name, age); // super关键字用来继承父类的属性
this.grade = grade;
}
greet() {
super.greet(); // 调用父类的同名方法
console.log(123); // 输出 123
}
study() {
console.log(this.name + " is studying.");
}
}
// 创建 Person 的实例
const alice = new Person("Alice", 30);
alice.greet(); // 输出 "Hello, Alice"
// 创建 Student 的实例
const bob = new Student("Bob", 20, "A");
bob.greet(); // 输出 "Hello, Bob" 然后输出 123
bob.study(); // 输出 "Bob is studying."
多态
多态即不同子对象统一调用同一个父对象的方法时,会根据自身内部的状态(各自的代码)产生各自的行为。
// 定义一个父类 Person
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log("Hello, " + this.name);
}
}
// 定义一个子类 Student 继承自 Person
class Student extends Person {
constructor(name, age, grade) {
super(name, age); // 调用父类构造函数
this.grade = grade;
}
greet() {
console.log("Hi, I am " + this.name + " and I am a student.");
}
}
// 定义另一个子类 Teacher 继承自 Person
class Teacher extends Person {
constructor(name, age, subject) {
super(name, age); // 调用父类构造函数
this.subject = subject;
}
greet() {
console.log("Hello, I am " + this.name + " and I teach " + this.subject + ".");
}
}
// 创建 Person 的实例
const alice = new Person("Alice", 30);
alice.greet(); // 输出 "Hello, Alice"
// 创建 Student 的实例
const bob = new Student("Bob", 20, "A");
bob.greet(); // 输出 "Hi, I am Bob and I am a student."
// 创建 Teacher 的实例
const charlie = new Teacher("Charlie", 40, "Math");
charlie.greet(); // 输出 "Hello, I am Charlie and I teach Math."
// 多态示例:定义一个数组包含不同类型的对象
const people = [alice, bob, charlie];
// 遍历数组并调用 greet 方法
people.forEach(person => person.greet());
五、总结
以上是JS面向对象编程的基本概念,让你更加直观地理解JS是如何创建对象,实现面向对象的。