再起航,我的学习笔记之JavaScript设计模式09(原型模式)

我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧!

我们之前分享过在JavaScript中继承是靠原型链来实现的,那么设计模式中就一定有原型模式,所以本次我们分享的就是原型模式

原型模式

原型模式(Prototype): 用原型实例指向创建对象的类,使用创建新的对象的类共享原型对象的属性以及方法。

假如我们有一个需求需要做图片轮播效果,但是,在这个页面又有多种效果,比如顶部的展示我需要从左向右切换,侧边栏的我要从上往下切换。这个时候我们要实现这个功能最好的方式就是通过创建对象来一一实现。

首先我们创建一个图像类

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.chageImage=function(){
		console.log('现在图片开始上下滑动');
	}
}

左右切换类

var LeftRightLoopImg=function(imgArr,container,arrow){
	//同样的我们用构造函数继承,继承图像类
	LoopImages.call(this,imgArr,container);
	//切换左右滑动剪头变量
	this.arrow=arrow;
	//重写继承的切换下一张图片方法
	this.changeImage=function(){
		console.log('现在图片开始左右滑动');
	}
}

接着我们创建一个左右轮播的实例看一下

var leftRightImg=new LeftRightLoopImg(
[
	'img1.jpg',
	'img2.jpg',
	'img3.jpg',
	'img4.jpg'
],
'leftright',
[
    'left.jpg',
    'right.jpg'
]);
leftRightImg.changeImage();//现在图片开始左右滑动

这种写法可以实现我们的功能,但是如果父类的构造函数中存在创建比较耗时的逻辑时,或者每次初始化都要做一些重复性的东西,我们这样创建对性能的消耗很大。

为了提高性能,我们需要有一种共享机制在每次创建基类时,将每次创建的一些简单而又差异化的属性放在构造函数中,将消耗资源比较大的方法放在基类的原型中,这样可以避免很多不必要的消耗。这就是我们原型模式的一个雏形。

我们再来看看改良过的例子
同样的我们建一个图像类

var LoopImages=function(imgArr,container){
	this.imagesArray=imgArr;//轮播图片数组
	this.container=container;//轮播图片容器
}

向图像类的原型添加方法

LoopImages.prototype={
		//创建轮播图片
		createImage:function(){
			console.log('创建方法');
		},
		//切换下一张图片
		changeImage:function(){
			console.log('切换方法');
		}
}

上下滑动切换类

var SlideLoopImg=function(imgArr,container){
	//构造函数继承图像类
	LoopImages.call(this,imgArr,container);

}

左右切换类

var LeftRightLoopImg=function(imgArr,container,arrow){
	//同样的我们用构造函数继承,继承图像类
	LoopImages.call(this,imgArr,container);
	//切换左右滑动剪头变量
	this.arrow=arrow;
}
LeftRightLoopImg.prototype=new LoopImages();
LeftRightLoopImg.prototype.changeImage=function(){
	console.log('现在图片开始左右滑动');
}

我们来测试一下

var leftRightImg=new LeftRightLoopImg([
	'img1.jpg',
	'img2.jpg',
	'img3.jpg',
	'img4.jpg'
],'leftright',[
'left.jpg',
'right.jpg'
]);
console.log(leftRightImg.container);//leftright
leftRightImg.changeImage();//现在图片开始左右滑动

原型对象是个共享的对象,那么无论是父类的实例对象还是子类的继承,都是对它的一个指向引用,所以原型对象才会被共享,那么对原型对象的扩展,无论是子类还是父类的实例对象都会继承下来。

我们来试一下

LoopImages.prototype.getImageLength=function(){
	return this.imagesArray.length;
}
LeftRightLoopImg.prototype.getContainer=function(){
	return this.container;
}
console.log(leftRightImg.getImageLength());//4
console.log(leftRightImg.getContainer());//leftright

这样我们就能总结出一个原型模式的特点,在任何时候都可以对基类或者子类进行方法的扩展,而且所有被实例化的对象或者类都能获取这些方法,这样给予我们对功能扩展的自由性。

不过原型模式更多的是用在对对象的创建上,如果我们要创建一个构造函数比较复杂或者耗时较长的实例对象,此时我们最好不要用new关键字去复制这些基类,但可以通过对这些对象属性或者方法进行复制来实现创建,这是原型模式的最初的思想。

接下来我们写一个原型模式对象复制的方法

function prototypeExtend(){
	var F=function(){},//缓存类,为实例化返回对象临时创建
	args=arguments,
	i=0,
	len=args.length;
	for(var i=0;i<args.length;i++){
		//遍历每个模板对象中的属性
		for(var j in args[i]){
			//将这些属性复制到缓存类原型中
			F.prototype[j]=args[i][j];
		}
	}
	//返回一个缓存类的实例
	return new F();
}

我们来看一下具体的应用

var grade=prototypeExtend({
	fractions:99,
	CSharp:function(){
		console.log(this.fractions);
	},
	Java:function(fractions){
	console.log(fractions);
	},
	JavaScript:function(){
	console.log('不及格');	
	}
	})

现在我们就可以不用new来创建对象而直接通过点语法去调用了,我们来看一下调用

grade.CSharp();//99
grade.Java(100);//100
grade.JavaScript();//不及格

也谢谢大家看到这里:)如果你觉得我的分享还可以请点击推荐,分享给你的朋友让我们一起进步~

好了以上就是本次分享的全部内容,本次示例参考自JavaScript设计模式一书,让我们一点点积累一点点成长,希望对大家有所帮助。

欢迎转载,转载请注明作者,原文出处。

posted @ 2017-08-18 08:25  东城慕水  阅读(571)  评论(1编辑  收藏  举报