面向委托的设计
假设软件中建模设计一些任务(“XYZ”,“ABC”等)。
首先定义一个名为Task的对象,它会包含所有任务都可以使用的具体行为。接着,对于每个任务(“XYZ”,“ABC”)都会定义一个对象来存储对应的数据和行为。开发者会把特定的任务对象都关联到Task功能对象,让它们在需要的时候可以进行委托。
let Task = {
setID: function(ID){ this.id = ID; },
outputID: function(){ console.log(this.id); }
}
// 让XYZ委托Task
let XYZ = Object.create(Task);
XYZ.prepareTask = function(ID,label){
this.setID(ID);
this.label = label;
};
XYZ.outputTaskDetails = function(){
this.outputID();
console.log(this.label);
}
在JavaScript中,[[Prototype]]原型链机制会把对象关联其他对象。无论怎么说,JavaScript中就是没有类似“类”的抽象机制。
委托行为意味着某些对象(XYZ)在找不到属性或者方法引用是会把这个请求委托给另一个对象(Task)。
ES6中的Class
现在我们来看看ES6的class机制,首先我们看下面的例子。
class Widget{
constructor(width,height){
this.width = width || 50;
this.height = height || 50;
this.$element = null;
}
render($where){
if(this.$element){
this.$element.css({
width: this.width + 'px',
height: this.height + 'px',
}).appendTo($where);
}
}
}
class Button extends Widget{
constructor(width,height,label){
super(width,height);
this.label = label || 'Default';
this.$element = $('button').text(this.label);
}
render($where){
super.render($where);
this.$element.click(this.onClick.bind(this));
}
onClick(evt){
console.log("Button" + this.label + " clicked");
}
}
ES6的class引入,使开发者不再引用杂乱的.prototype,也可以通过super实现相对多态,这样任何方法都可以引用原型链上层的同名方法。
可以通过extends很自然的扩展对象子类型。
ES6的class语法是向JavaScript中引入了全新的“类”机制,其实不是这样,class基本上只是现有的[[Prototype]]机制的一种语法糖。
其实我们还是可以在class机制中使用.prototype
class C {
constructor(){
C.prototype.count++;
console.log("Hello: " + this.count);
}
}
C.prototype.count = 0;
let c1 = new C(); // Hello: 1
let c2 = new C(); // Hello: 2
c1.count === 2; // true
c1.count === c2.count; // true