原型实例(Prototype)
原型模式:用原型实例指向创建对象的类,使用于创建新的对象的类共享原型对象的属性和方法
7.1 语言中的原型
在javascript中的继承是靠原型链实现的,那么这就是Javascript中的原型模式把?
嗯,原型模式就是将原型对象指向创建对象的类,使这些类共享原型对象的方法与属性。当然Javascript是基于原型链实现对象之间的继承,这种继承是基于一种对属性或者方法的共享,而不是对属性和方法的复制
7.2 创建一个焦点图
举个例子:假设页面中有很多的焦点图(网页中很常见的一种图片轮播,切换效果),那么我们要实现这些焦点图最好的方式就是通过创建对象来一一实现的,所以我们就需要有一个焦点图类,比如我们把这个类定义为 LoopImages
// 图片轮播类
var LoopImages = function(imgArr, container) {
this.imagesArray = imgArr; // 轮播图片数组
this.container = container; // 轮播图片容器
this.createImage = function(){} // 创建轮播图片
this.changeImage = function(){} // 切换下一章图片
}
// 我们应该抽象出一个基类,让不同特效类去继承这个基类,然后对于差异化的需求通过重写这些继承下来的属性或方法来解决,当然不同的子类之间可能存在不同的
// 结构样式
// 上下滑动切换类
var SlideLoopImg = function(imgArr, container) {
// 构造函数继承图片轮播类
LoopImages.call(this, imgArr, container);
// 重写继承的切换下一张图片的方法
this.changeImage = function(){
console.log('SlideLoopImg changeImage function');
}
}
// 渐隐切换类
var FadeLoopImg = function(imgArr, container, arrow) {
LoopImages.call(this, imgArr, container);
// 切换箭头私有变量
this.arrow = arrow;
this.changeImage = function(){
console.log('FadeLoopImg changeImage function');
}
}
// 我们创建一个显隐轮播图片测试实例很容易
// 实例化一个渐隐切换图片类
var fadeImg = new FadeLoopImg([
'01.jpg',
'02.jpg',
'03.jpg',
'04.jpg'
],'slide', [
'left.jpg',
'right.jpg'
]);
fadeImg.changeImage(); // FadeLoopImg changeImage function
7.3 最优的解决方案
// 图片轮播类
var LoopImages = function(imgArr, container) {
this.imagesArray = imgArr; // 图片轮播组
this.container = container; // 轮播图片容器
}
LoopImages.prototype = {
// 创建轮播图片
createImage : function() {
console.log('LoopImages createImage function');
},
// 切换下一张图片
changeImage : function() {
console.log('LoopImages changeImage function');
}
}
// 上下滑动切换类
var SlideLoopImg = function(imgArr, container) {
// 构造函数继承图片轮播类
LoopImages.call(this, imgArr, container);
}
SlideLoopImg.prototype.changeImage = function() {
console.log('SlideLoopImg changeImage function');
}
// 渐隐切换类
var FadeLoopImg = function(imgArr, container, arrow) {
LoopImages.call(this, imgArr, container);
// 切换箭头私有变量
this.arrow = arrow;
}
FadeLoopImg.prototype = new LoopImages();
FadeLoopImg.prototype.changeImage = function() {
console.log('FadeLoopImage changeImage function');
}
// 测试用例
console.log(fadeImg.container); // slide
fadeImg.changeImage(); // FadeLoopImage changeImage function
7.4 原型的拓展
你知道关于原型对象的一个特点吗?
原型对象是一个共享的对象,那么不论是父类的实例对象或者是子类的继承,都是都它的一个指向引用,所以原型对象才会被共享,既然被共享,那么对于原型对象的拓展,不论是子类还是父类的实例对象都会继承下来。
// 测试代码
LoopImages.prototype.getImageLength = function() {
return this.imagesArray.length;
}
FadeLoopImg.prototype.getContainer = function() {
return this.container;
}
console.log(fadeImg.getImageLength()); // 4
console.log(fadeImg.getContainer()); // slide
7.5 原型继承
/*****
* 基于已经存在的模版对象克隆出新对象的模式
* arguments[0], arguments[1], argument[2]: 参数1, 参数2,参数3 表示模版对象
* 注意。这里对模版引用类型的属性实质上进行了浅复制(引用类型属性共享)
* 当然根据需求可以自行深复制
*****/
function prototypeExtend() {
var F = function() {}, // 缓存类,为实例化返回对象临时创建
args = arguments, // 模版对象参数序列
i = 0,
len = args.length;
for(; i < len; i++){
// 遍历每个模版对象中的属性
for( var j in args[i]) {
// 将这些属性复制到缓存类的原型中
F.prototype[j] = args[i][j];
}
}
// 返回缓存类的一个实例
return new F();
}
比如企鹅游戏中我们创建一个企鹅基类,只是提供了一些动作模版对象,我们就可以通过实现对这些模版对象的继承来创建一个企鹅实例对象
var penguin = prototypeExtend({
speed : 20,
swim : function(){
console.log('游泳速度' + this.speed);
}
},{
run : function(speed) {
console.log('奔跑速度' + speed);
}
},{
jump : function() {
console.log('跳跃动作');
}
})
// 既然通过prototypeExtend 创建的是一个对象, 我们就无需在再用new去创建的实例对象,我们可以直接使用这个对象
penguin.swim(); // 游泳速度 20
penguin.run(10); // 奔跑速度 10
penguin.jump(); // 跳跃动作