zoukankan      html  css  js  c++  java
  • 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:稳妥构造函数和寄生类似。

  • 相关阅读:
    U-Boot新手入门
    安装交叉编译工具
    Makefile 工程管理
    gcc基本用法
    poj 3264 Balanced Lineup
    hdoj 1166 敌兵布阵
    poj 1363 Rails
    poj 1028 Web Navigation
    zoj 3621 Factorial Problem in Base K
    poj1861最小生成树
  • 原文地址:https://www.cnblogs.com/linkhtml/p/5670759.html
Copyright © 2011-2022 走看看