类的设计模式:实例化、继承和(相对)多态。
JavaScript通过原型链,在两个对象之间创建一个关联。这样,一个对象就可以通过委托访问另一个对象的属性和函数,从而达到“继承”的实现。
下面来看一个例子:
function Foo(name) {
this.name = name;
}
Foo.prototype.myName = function () {
return this.name;
};
function Bar(name, label) {
Foo.call(this, name);
this.label = label;
}
Bar.prototype = new Foo(); //实现prototype的关联
Bar.prototype.myLabel = function () {
return this.label;
};
var a = new Bar("a", "obj a");
a.myName(); // "a"
a.myLabel(); // "obj a"
构造函数和实例原型的关系图(红色的就是原型链)
原型prototype
每个函数都有一个prototype属性,函数的prototype属性指向了一个对象,这个对象正是调用该构造函数而创建的实例的原型。例子中Bar.prototype就是实例a的原型。
proto
这是每一个JavaScript对象(除了 null )都具有的一个属性,叫proto,这个属性会指向该对象的原型。
a.__proto__ === Bar.prototype //true
Bar.prototype.__proto__ === Foo.prototype //true
constructor
constructor,每个原型都有一个 constructor 属性指向关联的构造函数。
Foo === Foo.prototype.constructor
为了方便理解,这里我们简单模拟实现new
function objectFactory() {
var obj = new Object(),Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
var ret = Constructor.apply(obj, arguments);
return typeof ret === 'object' ? ret : obj;
};
下面介绍,另外两种写法:
Object.create(行为委托设计模式)
var Foo = {
init: function(name){
this.name = name;
},
myName: function(){
return this.name;
}
};
var Bar = Object.create(Foo);
Bar.setup = function(name, label){
// 委托调用
this.init(name);
this.label = label;
};
Bar.myLabel = function(){
return this.label;
};
var a = Object.create( Bar );
a.setup("a", "obj a");
a.myName(); // "a"
a.myLabel(); // "obj a"
简单模拟实现Object.create
Object.create = function (o) {
var F = function () {};
F.prototype = o;
return new F();
};
class(class 语法可以简洁地定义类方法)
class Foo {
constructor(name) {
this.name = name;
}
myName() {
return this.name;
}
}
class Bar extends Foo {
constructor(props, label) {
super(props);
this.label = label;
}
myLabel() {
return this.label;
}
}
var a = new Bar("a", "obj a");
a.myName(); // "a"
a.myLabel(); // "obj a"