摘要:
本文将深入探讨JavaScript面向对象编程中的封装、继承和多态的概念,并通过丰富的代码示例来解释这些概念在实际开发中的应用。通过这些知识,我们将更好地利用JavaScript的面向对象编程特性,提高代码质量和复用性。
一、封装:
封装是将数据(属性)和操作数据的函数捆绑在一起,形成一个独立的实体。这有助于隐藏对象的内部实现细节,只暴露必要的接口。
示例1:
javascript复制代码
function Car(make, model, year) {
var car = this;
car.make = make;
car.model = model;
car.year = year;
car.getInfo = function() {
return "品牌:" + car.make + ", 型号:" + car.model + ", 制造年份:" + car.year;
};
}
var myCar = new Car("Toyota", "Corolla", 2020);
console.log(myCar.getInfo()); // 输出:品牌:Toyota, 型号:Corolla, 制造年份:2020
在这个例子中,我们通过封装创建了一个Car对象,该对象具有make、model和year属性,以及一个用于获取车辆信息的getInfo方法。封装使我们能够隐藏对象的内部实现细节,只暴露必要的接口。
二、继承:
继承是一种机制,允许一个类继承另一个类的属性和方法。这使得我们可以创建更具体的类,继承更一般的类的属性和方法。
示例2:
javascript复制代码
function Vehicle(make, model) {
this.make = make;
this.model = model;
}
Vehicle.prototype.move = function() {
return "车辆正在移动";
};
function Car(make, model) {
Vehicle.call(this, make, model); // 调用父类的构造函数
}
Car.prototype = Object.create(Vehicle.prototype); // 继承父类的原型链
Car.prototype.constructor = Car; // 修复构造器指向
Car.prototype.move = function() { // 重写父类的 move 方法
return "汽车正在移动";
};
在这个例子中,我们创建了一个Vehicle类作为基类,并定义了一个move方法。然后,我们创建了一个Car类作为子类,继承了Vehicle类的属性和方法,并重写了move方法。通过继承,我们可以重用父类的代码,并且子类可以添加或覆盖父类的行为。
示例3:
首先,我们定义了一个Employee类作为基类:
javascript复制代码
function Employee(name, position) {
this.name = name;
this.position = position;
this.greet = function() {
console.log("我是" + this.name + ",我的职位是" + this.position);
};
}
然后,我们创建了两个子类:Manager和Engineer,分别继承了Employee类:
javascript复制代码
function Manager(name, position, reports) {
Employee.call(this, name, position); // 调用父类的构造函数
this.reports = reports;
this.promote = function() {
console.log("提升员工");
};
}
Manager.prototype = Object.create(Employee.prototype); // 继承父类的原型链
Manager.prototype.constructor = Manager; // 修复构造器指向
Manager.prototype.promote = function() { // 重写父类的 promote 方法
for (var i = 0; i < this.reports.length; i++) {
console.log(this.reports[i] + " 被提升为 " + this.position);
}
};
function Engineer(name, position, skills) {
Employee.call(this, name, position); // 调用父类的构造函数
this.skills = skills;
this.specialty = function() {
console.log("我的专长是 " + this.skills);
};
}
Engineer.prototype = Object.create(Employee.prototype); // 继承父类的原型链
Engineer.prototype.constructor = Engineer; // 修复构造器指向
Engineer.prototype.specialty = function() { // 重写父类的 specialty 方法
for (var skill in this.skills) {
console.log(skill + ": " + this.skills[skill]);
}
};
接下来,我们创建了一些实例并测试它们的行为:
javascript复制代码
var john = new Engineer("John", "软件工程师", ["JavaScript", "HTML", "CSS"]);
var lisa = new Manager("Lisa", "项目经理", ["Emily", "Michael"]);
john.greet(); // 输出:我是 John,我的职位是软件工程师
lisa.greet(); // 输出:我是 Lisa,我的职位是项目经理
john.specialty(); // 输出:JavaScript: John, HTML: John, CSS: John
lisa.promote(); // 输出:Emily 被提升为软件工程师,Michael 被提升为软件工程师
在这个例子中,我们通过封装创建了Employee、Manager和Engineer对象,每个对象都有自己的属性和方法。Manager和Engineer类继承了Employee类,并添加了自己的属性和方法。我们还演示了多态性,即不同的对象可以调用相同的方法并表现出不同的行为。