Javascript面对对象. 第四篇

原型模式创建对象也有自己的缺点,它省略看构造函数传参初始化这一过程,带来的缺点就是初始化的值都是一致的。

而原型最大的缺点就是它优点,那就是共享。

原型中所有属性是被很多实例共享的,共享对于函数非常合适,对于包含基本值的属性也还可以,但如果属性包含引用类型。

就存在一定的问题:

	function Box(){};
	    Box.prototype={
	    	Constructor:Box,
	    	name:"link",
	    	age:25,
	    	family:['哥哥','弟弟','妹妹'],
	    	run:function(){
	    		return this.name+this.age+'运行中。。。'
	    	}
	    }
	    var box1=new Box();
	    alert(box1.family)
	    box1.family.push('姐姐')  //添加一个引用类型
	    alert(box1.family)       // 输出      哥哥弟弟妹妹姐姐
	    
	    var box2=new Box();
	    alert(box2.family)  //共享了box1添加的引用类型的原型    // 输出    哥哥弟弟妹妹姐姐

 ps:数据共享的缘故,导致很多开发者放弃使用原型,因为每次实例化出的数据需要保留自己的特性,而不能共享。

为了解决构造传参和共享问题,可以组合构造函数+原型模式

function Box(name,age){            //不共享的使用构造函数
	this.name=name;
	this.age=age;
	this.family=['哥哥','弟弟','妹妹'];
}
	 Box.prototype={   //共享的使用原型模式
	 	constructor:Box,
	 	run:function(){
	 	  return this.name+this.age+'运行中。。。'
	 	}
	 }
	 var box1=new Box('link',25);
	 box1.family.push('姐姐')
	 alert(box1.run())
	 alert(box1.family)   // 输出    哥哥弟弟妹妹姐姐
	 
	 var box2=new Box('links',25);
	 alert(box2.run())
	 alert(box2.family)    // 输出        哥哥弟弟妹妹

 ps:这种混合模式很好的解决了传参和引用共享的大难题。是创建对象比较好的方法。

 原型模式,不管你是否调用了原型中的共享方法,它都会初始化原型中的方法,并且在声明一个对象时,构造函数+原型部分很让人怪异,最好就是把构造函数和原型封装到一起。为了解决这个问题,我们可以使用动态原型模式

	      //可以将原型封装到构造函数里面
		function Box(name,age){
			this.name=name;
			this.age=age;
			alert('初始化开始')
		Box.prototype.run=function(){
			return this.name+this.age+'运行中...'
		}
			alert('初始化结束')
		}
		//原型初始化,执行一次就行,没有必要每次都构造函数实例化的时候初始化!
		var box1=new Box('link',53);
		alert(box1.run())
		
		var box2=new Box('that',5311);
		alert(box2.run())

 原型初始化,执行一次就行,没有必要每次都构造函数实例化的时候初始化!

          function Box(name,age){
			this.name=name;
			this.age=age;
			
			if(typeof this.run!='function'){  //查看this是否有run
				alert('初始化开始')
		Box.prototype.run=function(){
			return this.name+this.age+'运行中...'
		}
		alert('初始化结束')
		}
			
		}
             //原型初始化,执行一次就行!
		var box1=new Box('link',53);
		alert(box1.run())
		
		var box2=new Box('that',5311);
		alert(box2.run())

 ps:使用动态原型模式,要注意一下,就是不可以再使用字面量的方式重写原型,因为会切断实例和新原型之间的关联。

如果这几种方式不能满足需求,可以使用一开始那种模式:寄生构造函数

	function Box(name,age){
			var obj = new Object();
			obj.name=name;
			obj.age=age;
			obj.run=function(){
			 return	this.name+this.age+"运行中....."
			}
			return obj
		}
		var box1=new Box('link',53);
    	alert(box1.run())

 ps:寄生构造函数,其实就是工厂模式+构造函数模式。这种模式比较通用,但是不能确定对象关系,所有,在可以使用之前所说的模式时,不建议使用此模式!

在什么情况下使用寄生构造函数比较合适呢?

假如要创建一个额外方法的引用类型。由于之前说明不建议直接使用String.porotype.addstring方法,

可以使用寄生构造的方式添加:

function mystring(string){
	var str=new String(string);
      str.addString=function(){
      	return this+',添加';
      }
      return str;
}
var box1=new mystring('link');
alert(box1.addString());

 在一些安全的环境中,比如禁止使用this和new,这里的this是构造函数里不使用this,这里的new是在外部实例化构造函数时不使用new,

这种创建方式叫稳妥构造函数

            function Box(name,age){
			var obj = new Object();
			obj.run=function(){
			 return	name+age+"运行中....."
			}
			return obj
		}
		var box1=Box('link',53);
    	    alert(box1.run())

 ps:稳妥构造函数和寄生类似。

posted @ 2016-07-14 16:08  IT温故而知新  阅读(189)  评论(0编辑  收藏  举报