面向委托的设计
假设软件中建模设计一些任务(“XYZ”,“ABC”等)。
首先定义一个名为Task的对象,它会包含所有任务都可以使用的具体行为。接着,对于每个任务(“XYZ”,“ABC”)都会定义一个对象来存储对应的数据和行为。开发者会把特定的任务对象都关联到Task功能对象,让它们在需要的时候可以进行委托。
let Task = {setID: function(ID){ this.id = ID; },outputID: function(){ console.log(this.id); }}// 让XYZ委托Tasklet 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: 1let c2 = new C(); // Hello: 2c1.count === 2; // truec1.count === c2.count; // true
