Prototype的机制到底是什么
- Prototype 机制就是指对象中的一个内部链接引用另一个对象
- 如果在第一个对象上没有找到需要的属性或者方法引用,引擎就会继续在 Prototype关联的对象上进行查找。
JavaScript 中这个机制的本质就是对象之间的关联关系
6.1 面向委托的设计
把思路从类和继承的设计模式转换到委托行为的设计模式
对象关联 OLOO,objects linked to other objects
- XYZ 对象(和 ABC 对象)委托了Task 对象
js
var Task = {
setID: function (ID) { this.id = ID; },
outputID: function () { console.log(this.id); }
};
// 让 XYZ 委托 Task
XYZ = Object.create(Task);
XYZ.prepareTask = function (ID, Label) {
this.setID(ID);
this.label = Label;
};
XYZ.outputTaskDetails = function () {
this.outputID();
console.log(this.label);
};
// ABC = Object.create( Task );
// ABC ... = ...
6.1.3 比较思维模型
面向对象
js
function Foo(who) {
this.me = who;
}
Foo.prototype.identify = function() {
return "I am " + this.me;
};
function Bar(who) {
Foo.call( this, who );
}
Bar.prototype = Object.create( Foo.prototype );
Bar.prototype.speak = function() {
alert( "Hello, " + this.identify() + "." );
};
var b1 = new Bar( "b1" );
var b2 = new Bar( "b2" );
b1.speak();
b2.speak();

简化版本
对象关联
js
Foo = {
init: function(who) {
this.me = who;
},
identify: function() {
return "I am " + this.me;
}
};
Bar = Object.create( Foo );
Bar.speak = function() {
alert( "Hello, " + this.identify() + "." );
};
var b1 = Object.create( Bar );
b1.init( "b1" );
var b2 = Object.create( Bar );
b2.init( "b2" );
b1.speak();
b2.speak();

6.2 类与对象
包含所有通用控件行为的父类(可能叫作 Widget)和继承父类的特殊控件子类的项目设计
在不使用任何"类"辅助库或者语法的情况下,使用纯JavaScript 实现类风格的代码
js
// 父类
function Widget(width, height) {
this.width = width || 50;
this.height = height || 50;
this.$elem = null;
}
Widget.prototype.render = function ($where) {
if (this.$elem) {
this.$elem.css({
width: this.width + "px",
height: this.height + "px"
}).appendTo($where);
}
};
// 子类
function Button(width, height, label) {
// 调用"super"构造函数
Widget.call(this, width, height);
this.label = label || "Default";
this.$elem = $("<button>").text(this.label);
}
// 让 Button"继承"Widget
Button.prototype = Object.create(Widget.prototype);
// 重写 render(..)
Button.prototype.render = function ($where) {
//"super"调用
Widget.prototype.render.call(this, $where);
this.$elem.click(this.onClick.bind(this));
};
Button.prototype.onClick = function (evt) {
console.log("Button '" + this.label + "' clicked!");
};
$(document).ready(function () {
var $body = $(document.body);
var btn1 = new Button(125, 30, "Hello");
var btn2 = new Button(150, 40, "World");
btn1.render($body);
btn2.render($body);
});
ES6的class语法糖 写法
js
class Widget {
constructor(width, height) {
this.width = width || 50;
this.height = height || 50;
this.$elem = null;
}
render($where) {
if (this.$elem) {
this.$elem.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.$elem = $("<button>").text(this.label);
}
render($where) {
super($where);
this.$elem.click(this.onClick.bind(this));
}
onClick(evt) {
console.log("Button '" + this.label + "' clicked!");
}
}
$(document).ready(function () {
var $body = $(document.body);
var btn1 = new Button(125, 30, "Hello");
var btn2 = new Button(150, 40, "World");
btn1.render($body);
btn2.render($body);
});
使用对象关联风格委托来更简单地实现 Widget/Button
js
var Widget = {
init: function (width, height) {
this.width = width || 50;
this.height = height || 50;
this.$elem = null;
},
insert: function ($where) {
if (this.$elem) {
this.$elem.css({
width: this.width + "px",
height: this.height + "px"
}).appendTo($where);
}
}
};
var Button = Object.create(Widget);
Button.setup = function (width, height, label) {
// 委托调用
this.init(width, height);
this.label = label || "Default";
this.$elem = $("<button>").text(this.label);
};
Button.build = function ($where) {// 委托调用
this.insert($where);
this.$elem.click(this.onClick.bind(this));
};
Button.onClick = function (evt) {
console.log("Button '" + this.label + "' clicked!");
};
$(document).ready(function () {
var $body = $(document.body);
var btn1 = Object.create(Button);
btn1.setup(125, 30, "Hello");
var btn2 = Object.create(Button);
btn2.setup(150, 40, "World");
btn1.build($body);
btn2.build($body);
});