面向对象模式创建多个轮播图(一)

这是我对PC站构建过程中面对多个类似功能模块情况下的思考与探索

首先,我先介绍一下比较常用的创建对象的三种方法:

#####1.构造函数模式 先看一段代码

  function person(name,age){
		this.name = name;
		this.age = age;
		this.say = function(){
			alert(this.name)
		}
	}
  var person1 = new person('小明',18);
  var person2 = new person('小红',24);
  person1.say(); // 浏览器弹出‘小明’
  person1.say(); // 浏览器弹出‘小红’

如果你对this还心存疑虑,请移步阮一峰博客: http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html 我们只说一下在new的过程中发生了什么

1.创建一个新的对象; 2.建构造函数的作用域赋给新对象(因此this指向了这个新对象); 3.执行构造函数中的代码(为这个新对象添加属性); 4.返回新对象;

通过new的过程,我们发现案例暴露出一个问题,那就是person1和person2使用的方法虽然是一模一样的,但是在new的过程中,person构造函数都为新对象创建了一个say()方法,这势必造成引擎不但要多读一遍代码,内存还要多浪费地方存储,相当于:

你是一个包工头,你手底下有两名工人,两名工人都要用锤子,你就买了两把锤子分别让工人戴在身上,可是JS的单线程规则就相当于你为两名工人制定了一个规则,就是同一时间段内,只能一个人用锤子,明明一个锤子能搞定的事你非要整两个,工人戴在身上累的够呛,你还多浪费了一份钱。

所以原型模式应运而生。 #####2.原型模式

    function person(){}
	person.prototype.say = function(){alert(this.name)}
	
	var person1 = new person();
	person1.name = '小明';
	person1.age = 18;
	person1.say(); // 浏览器弹出‘小明’
	
	var person2 = new person();
	person2.name = '小红';
	person2.age = 24;
	person2.say(); // 浏览器弹出‘小红’

这里可能让你疑惑的应该是prototype这个东西,说一下,函数的prototype属性是函数创建之初JS引擎自动为函数生成的一个对象,我们称这个对象为原型对象,这个对象默认有两个属性

①constructor

②_ _ proto _ _ (这个属性是浏览器厂商自己实现的,并非JS引擎实现)

注意: 只有函数有prototype对象,而且只有prototype对象有constructor属性。 通过构造函数构造出的对象和我们自己创建的普通对象只有_ _ proto _ _ 这个属性,并且我们可以通过_ _ proto _ _ 来访问构造出此对象的构造函数的prototype对象。代码如下:

    function person(){}
	person.prototype.say = function(){alert(this.name)};
	var person1 = new person();
	var a = {};

	console.log(person.prototype)
	console.log(person1)
	console.log(a)

######注:constructor属性存在的意义在于能够让构造函数new出的对象知道是谁把它构造出的,相当于: 有一天,小明去邻居小红家玩,小红的爸爸叫老王,老王正好回家,进门看了小明一会说:“我是你爸爸”。小明就蒙逼了,当即回家告老爹,老爹一气之下去验了DNA,发现小明的亲爹果然是老王。那么老王就是person()构造函数,小明就是person1对象,小红就是person2对象,这个DNA就是constructor,小明之所以能找到亲爹就是因为DNA(constructor)的存在。 ######但是不得不说constructor属性在我们一般开发工作当中是用不到的,只有你去构建大型框架类JS时才用的上。

根据这个图我们可以证明出:

console.log(person.prototype === person1.__proto__)//true
console.log(person.prototype.__proto__ === a.__proto__)//true
console.log(person1.__proto__.__proto__ === a.__proto__)//true

细心的同志可能发现了person.prototype上有一个say方法,我们并没有在person1对象上直接定义这个方法,但开头我们写的代码已经验证了say方法是可用的,这是因为: ######构造出的对象person1能通过_ _ proto _ _来访问这个方法

这里说明一下person.prototype并非只能添加方法,也可以在prototype添加基础数据类型的属性: person.prototype.name = '小明'; ######或者 person.prototype.name = '小红';

但是这样person.prototype.name只能添加一个数据,这对于我们要创建两个实例的案例来说是没有任何意义的

这就解决了构造函数不能解决的方法重复问题,但是新问题又是显而易见的,因为要为每个对象添加特定的属性,还要通过手动添加的方式,如果要是能通过构造函数的方式把参数传进去就好了,对吧。

那么构造函数和原型的组合模式就这么产生了

#####3.构造函数和原型的组合模式

    function person(name,age){
		this.name = name;
		this.age = age;
	}
	person.prototy.say = function(){
		alert(this.name)
	}
	
	var person1 = new person('小明',18);
	person1.say(); //弹出小‘小明’

	var person2 = new person('小红',24);
	person2.say(); //弹出‘小红’

这样的组合模式就能满足我们的使用需求了,能传参数,有公共的方法,灵活性和代码性能都有了提升,原理就不用多说了,完全就是把构造函数和原型模式的优点组合在了一起

######由于轮播图具体代码部分篇幅较长,我决定这一题目分为两篇来写,下一篇我们就把工作中遇到的一个页面多个不同轮播图的情况用组合构造模式创建对象的方式解决,敬请期待。