javaScript设计模式-原型模式

Prototype(原型)模式

Prototype 模式是基于原型继承的模式,可以在其中创建对象,作为其他对象的原型。prototype 对象本身实际上是用作构造函数创建每个对象的蓝图。如果所用构造函数的原型包含一个名为 name 的属性,那么由同样的构造函数创建的每个对象也会有同样的属性。

模式不仅是一种实现继承的简单方法,它也可以带来性能的提升:在一个对象中定义一个函数,它们都是由引用创建(因此所有子对象都指向相同的函数),而不是创建它们自己的单份拷贝。

在 ECMAScript 标准所定义的,那些有趣的、真正的原型继承要求使用 Object.create 创建一个对象,拥有指定原型和可选的属性(例如:Object.create (prototype,optionalDescriptiorObjects))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var myCar = {
name: "Ford Escort",
drive: function() {
console.log("Weeee. I'm driving");
},

panic: function() {
console.log("Wait. How do you stop this thing?");
}
};

var yourCar = Object.create(myCar);

console.log(yourCar.name); // Ford Escort

Object.create 还允许我们轻松实现差异继承等高级概念,通过差异继承,对象可以直接继承自其他对象。Object.create 允许我们使用第二个提供的参数来初始化对象属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var vehicle = {
getModel: function() {
console.log("The model of this vehicle is.." + this.model);
}
};

var car = Object.create(vehicle, {
id: {
value: 1,
enumerable: true
},

model: {
value: "Ford",
enumerable: true
}
});

// car
// {id: 1, model: "Ford"}
/*
id: 1
model: "Ford"
__proto__:
getModel: ƒ ()
__proto__: Object
*/

在这里,可以使用对象字面量在 Object.create 的第二个参数上初始化属性,并且对象字面量采用的语法与 Object.defineProperties 和 Object.defineProperty 方法所使用的语法相似

如果希望在不直接使用 Object.create 的情况下实现 Prototype 模式,我们可以按章上面的示例模拟该模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var vehiclePrototype = {
init: function(carModel) {
this.model = carModel;
},

getModel: function() {
console.log("the model of this vehicle is.." + this.model);
}
};

function vehicle(model) {
function F() {}
F.prototype = vehiclePrototype;

var f = new F();
f.init(model);

return f;
}

var car = vehicle("Blue");
car.getModel();

这个方案不允许用户以同样的方式定义只读属性(因为如果不小心,vehiclePrototype 可能会被改变)

最后一种可供选择的 Prototype 模式实现是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
var beget = (function() {
function F() {}

return function(proto) {
F.prototype = proto;
return new F();
};
})();

var s = beget({
value: 1
});
console.log(s.value);