四、混合对象“类”:
? 在研究类的具体机制之前,首先介绍 面向类的设计模式:实例化(instantiation)、继承(inheritance)和(相对)多态(polymorphism)。
一)、类理论:
? 面向对象编程强调的是数据和操作数据的行为本质上是互相关联的。
1、“类“设计模式:
? 类是一种设计模式,有多种高级设计模式建立在面向对象类的基础上:迭代器模式、观察者模式、工厂模式、单例模式等等。
2、JavaScript中的”类“:
? 尽管ES6中加入了class关键字,但是JS中实际上并没有类。由于类是一种设计模式,因此可以用一些方法近似实现类的功能。
二)、类的机制:
? 在面向类的语言中,必须将类实例化才可以对抽象化的类进行操作。
- 类通过复制操作被实例化为对象形式;
- 类实例是由一个特殊的类方法共造的,这个方法名通常和类名相同,被称为构造函数;
三)、类的继承:
? 我们常说子类继承父类,但是用子类DNA是继承父类DNA会更好理解。类通过继承和方法重写实现多态。
-
多态并不表示子类和父类有关联,子类得到的只是父类的一份副本。类的继承其实就是复制。
-
在大多数面向类语言中,可以使用super来在子类中引用父类。
-
有些语言允许多重继承,这样会导致”钻石继承“,但是JS本身并不提供多重继承。
四)、混入:
? 在继承或者实例化时,JS的对象机制并不会自动执行复制行为。即JS中只有对象,并不存在可以被实例化的“类”。JS使用 混入来模拟类的复制行为。
1、显式混入:
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("...")
},
drive: function () {
this.ignition();
}
};
var Car = mixin(Vehicle, {
wheels: 4,
drive: function() {
Vehicle.drive.call(this);
console.log("...");
}
})
-
函数实际上没有被复制,复制的是函数引用。
-
Vehicle.drive.call(this);就是我们所说的显式多态,这里利用显式绑定调用Vechicle对象的drive方法,并把this绑定在Car对象上,确保drive()在Car对象的上下文中执行。
-
使用显式伪多态会使代码更加复杂、难以阅读并且南移维护。
-
此外还有 混合复制、寄生继承两种显式混入。
2、隐式混入:
? 类似显式伪多态,具有一样的问题。
五)、小结:
? 类意味着复制,传统的类被实例化时,它的行为会被复制到实例中。类被继承时,行为也会被复制到子类中。
? 混入模式可以用来模拟类的复制行为,但是通常会产生丑陋并且脆弱的语法。此外,显式混入实际上无法完全模拟类的复制行为,因为对象只能复制引用,无法复制被引用的对象或者函数本身。
? 总结,在JS中模拟类得不偿失。