每日读《你不知道的JavaScript(上)》| 类
引言
上一篇文章我们介绍完了对象的知识,了解了对象的行为和特性,所以这里我们就来到了“类”的技能点。
借此机会也夯实一下面向对象的基础吧~
类的基础概念
什么是类?
类就是对某种统一行为或特征的抽象
比如:
人类可以比作一个类,下面的男人、女人等等都继承了人类的基本特征,同时男人女人等又有各自的特殊能力,可以理解为他们各自的数据不同。
男人/女人 = 实例化
男人/女人 -> 人类(继承)
还有一个概念叫多态。
多态意味着,父类的通用行为可以被子类更特殊的行为重写。
什么是实例化
书中提到了一个很有意思的描述,把实例化的过程比作蓝图复现成现实世界中的建筑。
我们也可以这样来理解实例化。
类就是规划的蓝图。
实例化就是把类变成可用对象的过程。
比如:
Class Person {
// ...
}
var man = new Person(); // 这就是实例化,这个 man 就是一个实例
类的继承
假设我们先定义一个类,然后再定义一个继承前者的类。
子类和父类的关系一目了然:
子类会包含父类行为的原始副本,但是也可以重写所有继承的行为甚至定义新行为。
多态
我们就来分析书中的例子。注意这里是伪代码哈。
class Vehicle { // 这里定义一个基类
engines = 1 // 引擎数量
function ignition() { // 打火
output("Turning on my engine.")
}
function drive() { // 启动
ignition()
output("Steering and moving forward!")
}
}
class Car inherits Vehicle { // 定义一个继承了 Vehicle 的 Car 类
wheels = 4 // 汽车是4轮驱动的
function drive() { // 重写 drive 方法,覆盖 Vehicle 中的 drive
inherited:drive() // 调用了基类的 drive 方法
output("Rolling on all " + wheels + " wheels!")
}
}
class SpeedBoat inherits Vehicle { // 定义了继承 Vehicle 的 SpeedBoat 类
engines = 2 // 两个引擎
function ignition() { // 覆盖了 Vehicle 的 ignition 方法
output("Turning on my " + engines + " engines.")
}
function pilot() { // 模拟驾驶快艇
inherited:drive() // 调用父类的 drive 方法
output("Speeding through the water with ease!")
}
}
多态性体现在 Car
和 SpeedBoat
类对 Vehicle
类的 drive
方法的覆盖上。
Car
类通过 inherited:drive()
调用了 Vehicle
类的 drive
方法。
而 SpeedBoat
类虽然没有直接覆盖 drive
方法,但是在其 pilot
方法中通过 inherited:drive()
调用了 Vehicle
类的 drive
方法。
由于 SpeedBoat
类覆盖了 ignition
方法,所以 pilot
方法中的 inherited:drive()
实际上会调用 SpeedBoat
类的 ignition
方法,而不是 Vehicle
类的。
这就是多态性的一种体现:子类可以定义与父类同名的方法,在调用时,会根据对象的实际类型来执行相应的方法。
最后有一点需要格外注意,我们讲述的是类的概念,但并不代表JavaScript中就能够进行类似的行为。
因为在 JavaScript 中不存在类。
混入
如果我们要把上述伪代码复现成真正的可执行JavaScript,那就需要手动模拟复制过程。
而这个模拟的过程称为混入。
function mixin(sourceObj, targetObj) {
for (var key in sourceObj) {
// 只会在不存在的情况下复制
if (!(key in targetObj)) {
targetObj[key] = sourceObj[key];
}
}
return targetObj;
}
var Vehicle = {
engines: 1,
ignition: function() {
console.log("Turning on my engine.");
},
drive: function() {
this.ignition();
console.log("Steering and moving forward!");
}
};
var Car = mixin(Vehicle, {
wheels: 4,
drive: function() {
Vehicle.drive.call(this); // 显示把 this 绑定到 Car 的上下文中
console.log("Rolling on all " + this.wheels + " wheels!");
}
});
我在想,这个简单地了解一下就好了,因为并不是很好的一种写代码的方式。
你要说它有啥意义...
书中描述:
混入模式(无论显式还是隐式)可以用来模拟类的复制行为,但是通常会产生丑陋并且脆弱的语法,比如显式伪多态(
OtherObj.methodName.call(this, ...)
),这会让代码更加难懂并且难以维护。
小结
我们简单介绍了类的概念,其实主要是面向对象的理念,比如继承、多态等等。
但其实在JavaScript中,并没有类这个东西。
我们所能做的只是尽可能模拟类的一些行为,但仍然会存在一些弊端。
我们下一章会讲到原型和原型链,留一个小小的悬念,JavaScript中真正的继承其实是通过原型链来实现的,敬请期待叭~😉😉
转载自:https://juejin.cn/post/7377697380215390245