原型模式:用原型实例指向创建对象的类,使用于创建新的对象的类共享原型对象的属性以及方法
需求1:创建轮播图
// 图片轮播类
const LoopImages = function(imgArr,container){
this.imagesArray = imgArr //轮播图片数组
this.container = container //轮播图片容器
this.createImage = function(){} //创建轮播图
this.changeImage = function(){} //切换下一张图片
}
需求2:轮播图可能会有不同的切换方式:上下切换、左右切换、渐隐切换
优化1:抽象出一个基类,让不同切换方式的类去基础基类,对于差异性的需求通过重写继承下来的属性或者方法
//上下滑动切换类
const SlideLoopImg = function(imgArr,container){
//构造函数继承图片轮播类
LoopImages.call(this.imgArr,container)
//重写继承的切换图片方法
this.changeImage = function(){
console.log('SlideLoopImg changeImage function')
}
}
//渐隐切换类
const FadeLoopImg = function(imgArr,container,arrow){
LoopImages.call(this,imgArr,container)
//切换箭头私有变量
this.arrow = arrow
this.changeImage = function(){
console.log('FadeLoopImg changeImage function')
}
}
//实例化一个渐隐切换图片类
const fadeImg = new FadeLoopImg(
['1.png','2.png','3.png'],
'slide',
['left.png','right.png']
)
fadeImg.changeImage();
问题:每次子类继承都要创建一个父类,若父类构造函数有耗时较长的逻辑,每次初始化都要坐一些重复性的东西,性能消耗很大
优化2:简单有差异的属性放在构造函数中,消耗资源较多的方法放在基类的原型中
//图片轮播类
const LoopImages = function(imgArr,container){
this.imagesArray = imgArr //轮播图片数组
this.container = container //轮播图片容器
}
LoopImages.prototype = {
createImage(){
//创建轮播图
},
changeImage(){
//切换下一张图片
}
}
//上下滑动切换类
const SlideLoopImg = function(imgArr,container){
//构造函数继承图片轮播类
LoopImages.call(this.imgArr,container)
}
SlideLoopImg.prototype = new LoopImages()
//重写继承的切换图片方法
SlideLoopImg.prototype.changeImage = function(){
console.log('SlideLoopImg changeImage function')
}
//渐隐切换类
const FadeLoopImg = function(imgArr,container,arrow){
LoopImages.call(this,imgArr,container)
//切换箭头私有变量
this.arrow = arrow
}
FadeLoopImg.prototype = new LoopImages()
FadeLoopImg.prototype.changeImage = function(){
console.log('FadeLoopImg changeImage function')
}
//实例化一个渐隐切换图片类
const fadeImg = new FadeLoopImg(
['1.png','2.png','3.png'],
'slide',
['left.png','right.png']
)
fadeImg.changeImage();
问题:基类的构造函数比较复杂、消耗性能时,多个子类的重复继承多次,消耗性能、耗时也会多次
优化3:不要通过new关键字去复制基类,而是通过对这些对象属性或者方法进行复制来实现创建
/*
* 基于已经存在的模板对象克隆出新对象的模式
* 参数为模板对象
* 注意:这里对模板引用类型的属性进行了浅复制(引用类型属性共享),当根据需求可以自行深复制(引用类型属性复制)
*/
function prototypeExtend(...args){
const F = function(){} //缓存类,为实例化返回对象临时创建
for(let i = 0,l=args.length;i<l,i++){
// 遍历每个模板对象中的属性
for(const o in args[i]){
// 将这些属性复制到缓存类原型
F.prototype[j] = args[i][j]
}
}
// 返回类的一个实例
return new F()
}
//例子
//企鹅游戏创建企鹅对象,没有且基类,只提供了一些动作模板对象
const penguin = prototypeExtend(
{ speed:20,swim(){console.log('游泳速度 '+this.speed)} },
{ run(speed){console.log('奔跑速度 '+ speed)} },
{ jump(){console.log('跳跃动作')} }
)
penguin.swim() //游泳速度 20
penguin.run(10) //奔跑速度 10
penguin.jump() // 跳跃动作
网友评论