深入理解JavaScript系列(17):面向对象编程之概论详细介绍
前言
本文是深入理解JavaScript系列的第17篇,讲解面向对象编程的概念、理论和实践。在JavaScript中,我们可以使用面向对象编程(Object-Oriented Programming,OOP)的方式,构建更灵活、可维护性更好的代码。
什么是面向对象编程?
面向对象编程是一种编程范式,它将程序分解成多个独立的对象,每个对象都是具有属性和方法的独立实体,这些对象之间可以进行交互、传递消息,从而实现程序的功能。对象一般由类(Class)定义,类是对象的模板,它定义了对象的属性和方法。
面向对象编程有三个基本特征:
- 封装(Encapsulation):将对象的属性和方法封装在一起,对外暴露的只是一个接口,这样外部代码无法直接操作对象的内部状态,从而保证对象的安全性和稳定性。
- 继承(Inheritance):可以通过继承实现代码重用,将共同的代码抽象到一个父类中,子类可以继承父类的属性和方法,同时可以重写和扩展父类的行为。
- 多态(Polymorphism):允许不同的对象对同一个方法作出不同的响应。
面向对象编程的实现方式
1. 原型式继承
JavaScript是基于原型的语言,对象可以通过原型的方式继承其他对象的属性和方法。例如:
var Parent = function(name) {
this.name = name;
};
Parent.prototype.sayHello = function() {
console.log('Hello, I am ' + this.name);
};
var Child = function(name, age) {
Parent.call(this, name); // 继承父类的name属性
this.age = age;
};
Child.prototype = new Parent(); // 设置原型为父类实例
Child.prototype.sayHello = function() {
console.log('Hello, I am ' + this.name + ', age ' + this.age); // 重写父类的sayHello方法
};
var child = new Child('Tom', 7);
child.sayHello();
在这个例子中,我们用 Child 继承了 Parent 的 name 属性,同时也通过原型的方式继承了 Parent 的 sayHello 方法。我们还重写了 Child 的 sayHello 方法,由于多态的特性,当我们调用 Child 实例的 sayHello 方法时,会调用 Child 的定义,而不是 Parent 的定义。
2. 类式继承
在 ES6 中,JavaScript 引入了类的概念。使用类式继承,可以更加清晰地表达类与类之间的继承关系,实现起来也更加直观。例如:
class Parent {
constructor(name) {
this.name = name;
}
sayHello() {
console.log('Hello, I am ' + this.name);
}
}
class Child extends Parent {
constructor(name, age) {
super(name); // 调用父类的构造函数
this.age = age;
}
sayHello() {
console.log('Hello, I am ' + this.name + ', age ' + this.age);
}
}
let child = new Child('Tom', 7);
child.sayHello();
我们可以看到,在类式继承中,用 class
定义了一个类,其中使用 extends
关键字继承了父类,使用 super
调用了父类的构造函数。在子类中重写了 sayHello
方法,实现了对父类方法的覆盖。
总结
面向对象编程是一种重要的编程范式,在 JavaScript 中,我们可以使用原型式继承、类式继承等方式实现面向对象编程。学习和使用OOP可以让我们更好地组织和管理代码,提高开发效率和代码质量。
示例1:游戏角色设计
通过面向对象编程的方法,我们可以设计出一个游戏角色的类,包括名称、生命值、攻击力和技能等属性和方法。例如:
class Character {
constructor(name) {
this.name = name;
this.maxHp = 100;
this.hp = 100;
this.atk = 10;
}
sayHello() {
console.log('Hello, I am ' + this.name);
}
attack(enemy) {
console.log(this.name + ' attacks ' + enemy.name + ', ' + this.atk + ' damage caused');
enemy.hurt(this.atk);
}
skill(enemy) {
console.log(this.name + ' uses skill on ' + enemy.name + ', ' + this.atk*2 + ' damage caused');
enemy.hurt(this.atk*2);
}
hurt(damage) {
console.log(this.name + ' is hurt, ' + damage + ' damage taken');
this.hp -= damage;
if (this.hp <= 0) {
console.log(this.name + ' is dead');
}
}
}
let player = new Character('阿达');
let enemy = new Character('兽人');
player.sayHello();
enemy.sayHello();
player.attack(enemy);
enemy.attack(player);
player.skill(enemy);
在这个例子中,我们通过类的方式定义了一个游戏角色 Character
,其中包括了 sayHello
、attack
、skill
、hurt
等属性和方法。我们还在构造函数中初始化了角色的生命值、攻击力等属性。在 attack
、skill
和 hurt
方法中,我们还使用了多态,让不同的角色对同一个方法作出不同的响应。
示例2:购物车设计
再举一个例子,假如我们正在设计一个购物车系统,需要支持添加、删除、修改和计算总价等操作。我们可以用面向对象编程的方法,设计一个购物车的类。例如:
class Cart {
constructor() {
this.items = [];
}
add(item) {
this.items.push(item);
console.log(item.name + ' added to cart');
}
remove(item) {
const index = this.items.findIndex(x => x.name === item.name);
if (index > -1) {
this.items.splice(index, 1);
console.log(item.name + ' removed from cart');
}
}
update(item, newQuantity) {
const index = this.items.findIndex(x => x.name === item.name);
if (index > -1) {
const oldQuantity = this.items[index].quantity;
this.items[index].quantity = newQuantity;
console.log(item.name + ' quantity updated from ' + oldQuantity + ' to ' + newQuantity);
}
}
getTotalPrice() {
let totalPrice = 0;
for (let item of this.items) {
totalPrice += item.price * item.quantity;
}
console.log('Total price: ' + totalPrice);
}
}
let cart = new Cart();
let apple = {
name: 'Apple',
price: 5,
quantity: 1
};
let banana = {
name: 'Banana',
price: 7,
quantity: 2
};
cart.add(apple);
cart.add(banana);
cart.getTotalPrice();
cart.remove(banana);
cart.update(apple, 3);
cart.getTotalPrice();
在这个例子中,我们通过类的方式定义了一个购物车类 Cart
,其中包括了 add
、remove
、update
和 getTotalPrice
等属性和方法。在 totalPrice
中,我们还使用了循环和累加的方法,计算出购物车中所有商品的总价。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入理解JavaScript系列(17):面向对象编程之概论详细介绍 - Python技术站