9、原型模式
原型模式:用原型实例指向创建对象的类,使用于创建新的对象的类共享原型的属性及方法
7.1创建一个焦点图
要实现这些焦点图最好的方式就是通过创建对象来一一实现,所以我们需要一个焦点图类
1 //图片轮播类 2 var LoopImages = function(imgArr, container){ 3 this.imageArray = imgArr; //创建轮播图片数组 4 this.container = container; //轮播图片容器 5 this.createImage = function(){}; //创建轮播图片 6 this.changeImage = function(){}; //切换下一张图片 7 }
如果一个页面有多个这类焦点图,其切换动画一般是多样化的,有的可能是上下切换,有的可能是左右切花,渐隐切换,缩放切换。。。,因此创建的轮播图片结构应该是多样化的,同样切换的效果也是多样化的,因此我们要抽象出一个基类,让不同的特效去继承这个基类,差异化通过重写这些继承下来的属性或者方法来解决。不同的子类之间可能存在不同的结构样式。
1 //上下滑动切花类 2 var SlideLoopImg = function(imgArr, container){ 3 //构造函数继承图片轮播类 4 LoopImages.call(this, imgArr, container); 5 //重写继承的切换下一张图片方法 6 this.changeImage = (){ 7 console.log("slideloopimg changeImage function"); 8 } 9 } 10 11 //渐隐切换类 12 var FadeLoopImg = function(imgArr, container, arrow){ 13 LoopImages.call(this, imgArr, container); 14 //切换剪头私有变量 15 this.arrow = arrow; 16 this.changeImage = function(){ 17 console.log("FadeLoopImg changeImage function"); 18 } 19 }
我们创建一个显隐轮播图片测试下
1 //创建一个显隐切换类 2 var fadeImg = new FadeLoopImg([ 3 'img01.jpg', 4 'img02.jpg', 5 'img03.jpg' 6 ],'slide',['left.jpg','right.jpg']); 7 8 fadeImg.changeImage();
7.2最优的解决方案
当你想到根据不同展示,来继承基类,并重写方法说明你掌握部分知识,但还不够。存在一些问题,首先看下LoopImage,作为基类要被子类继承,那么将属性和方法都写在基类的构造函数里边会有一些问题,比如每次子类继承都要创建一次父类,每次初始化都做一些重复性的东西,这样性能消耗较长的逻辑及性能,为了避免不必要的消耗,可以采用原型链。
1 //图片轮播类 2 var LoopImages = function(imgArr, container){ 3 this.imageArray = imgArr; //轮播图片数组 4 this.container = container; //轮播图片容器 5 } 6 7 LoopImages.prototype = { 8 //创建轮播图片 9 createImage : function(){ 10 console.log('LoopImages createImage function'); 11 }, 12 //切换下一张图片 13 changeImage : function(){ 14 console.log('LoopImages changeImage function'); 15 } 16 } 17 18 19 //上下滑动切换 20 21 var slideloopimg = function(imgArr, container){ 22 //构造函数继承图片轮播类 23 LoopImages.call(this, imgArr, container); 24 } 25 26 slideloopimg.prototype = new LoopImages(); 27 //重写继承的切换下一张图片方法 28 slideloopimg.prototype.changeImage = { 29 console.log("slideloopimg changeImage function"); 30 } 31 32 33 //渐隐切换类 34 var FadeLoopImg = function(imgArr, container, arrow){ 35 LoopImages.call(this, imgArr, container); 36 //切换箭头私有变量 37 this.arrow = arrow; 38 } 39 40 FadeLoopImg.prototype = new LoopImages(); 41 FadeLoopImg.prototype.changeImage = { 42 console.log('FadeLoopImg changeImage function'); 43 }
测试用例
1 console.log(fadeImg.container); //slide 2 fadeImg.changeImage();
7.3原型的拓展
原型还有一个特点,原型对象是一个共享的对象,那么无论是父类的实例对象或是子类的继承都是对它的一个指向引用,所以原型对象才回被共享。既然被共享,那么对原型对象的拓展,无论是子类或者父类的实例对象都会继承下来。
1 LoopImages.prototype.getImageLength = function(){ 2 return this.imageArray.length; 3 } 4 5 FadeLoopImg.prototype.getContainer = function(){ 6 return this.container; 7 }
这一点要注意,由于这种方式太自由,不要随意去做,否则修改类的其它属性或者方法都有可能会影响到其他人。
7.4原型继承
不过原型模式更多的是用在创建对象的创建上。比如创建一个实例对象的构造函数比较复杂,或者耗时比较长,或者创建多个对象来实现,此时最好不用使用new关键字复制这些类,但可以通过对这些对象属性或者方法进行复制来实现创建。
1 function prototypeExtend(){ 2 var F = function(){}, //缓存类,为实例化返回对象临时创建 3 args = arguments, //模版对象参数序列 4 i = 0, 5 len = arg.length; 6 for(; i < len; i++){ 7 //遍历每个模版对象中的属性 8 for(var j in args[i]){ 9 //将这些属性复制到缓存类原型中 10 F.prototype[j] = args[i][j]; 11 } 12 } 13 //返回缓存类的一个实例 14 return new F(); 15 }
可以这样使用
1 var pg = prototypeExtend({ 2 spend : 20, 3 swim : function(){ 4 console.log('swin' + this.spend); 5 } 6 },{ 7 run : function(speed){ 8 console.log('run' + speed); 9 } 10 })
我们不需要在用new 去创建新的实例对象,
pg.swin(); pg.run(10)
浙公网安备 33010602011771号