混合对象“类”
Javascript 不存在真正的类,以下的所有类都是“假类”。
一、类
类的设计模式:实例化、继承、(相对多态)。
类的机制:类实例是由一个特殊的类方法构造的。这个方法名通常和类名相同,被称为构造函数。
类的继承:子类相对于父类是一个独立并且完全不同的类。子类会包含父类行为的原始副本,但可以重写所有的继承行为甚至定义新行为。
多态:子类可以使用相对多态(super)来引用父类中的方法。子类也可以通过重写该方法来改变原始对父类方法的继承引用。△super:超类(当前类的父类/祖父类)。
注意:
- Js中父类和子类的关系只存在于两者构造函数对应的 .prototype 对象中。
- 多态中不同层次的方法名可以定义多次。
- 多态并不表示子类和父类有关联,子类得到的只是父类的副本。若是子类对继承到的一个方法进行重写,不会影响到父类的方法。
- 方法定义的多态性取决于你是在哪个类实例中引用它(子类和父类都定义同一个方法并都使用,子类使用的是子类中定义的方法,父类中使用父类中定义的方法)。
二、混入
ES6提供class语法糖之前,JS没有可以实例化的“类”,只有对象。为了实现采用模拟类的复制行为,就是 混入。
<一>显式混入
手动复制在许多库和框架中被称为 extend(…),方便理解我们称之 mixin(…)。
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("111");
},
drive: function() {
this.ignition();
console.log("222");
}
}
var Car = mixin(Vehicle, {
wheels: 4,
drive: function() {
Vehicle.drive.call(this);
console.log("333");
}
})
解析:
1、先遍历 sourceObj 的属性,在不存在该属性的情况下复制。
2、调用 mixin 方法,其中 Vehicle.drive.call(this) 就是显式多态,绑定 this 到 Car 对象。相当于继承。
注意:
- 函数无法真正的复制,只能复制对共享函数对象的引用。如果修改了共享函数对象,那父对象和子对象都会受到影响。
- 只在能提高代码可读性的前提下使用显式混入,避免使用增加代码理解难度,让对象关系更加复杂的模式。
<二>隐式混入
var Something = {
cool: function() {
this.greeting = "hello world";
this.count = this.count ? this.count + 1 : 1;
}
}
var Another = {
cool: function() {
Something.cool.call(this);
}
}
Another.cool();
Another.greeting; //hello world
Another.count; //1
解析:这类技术利用了 this 的重新绑定功能。但 Something.cool.call(this) 仍然无法变成相对引用。