Javascript高级程序设计——14.面向对象与原型(2)

1、创建原型访问prototype有两种方法

(1)构造函数实例方法创建

构造函数:在对象创建或者实例化时候被调用的方法。通常使用该方法来初始化数据成员和所需资源。

构造器Constructor不能被继承,因此不能重写Overriding,但可以被重载Overloading 

function Box(){
		...
    	}

    a、对象名访问prototype;

	var box=new Box();
	//alert(box.prototype);  //使用对象实例无法访问到prototype
	alert(box.__proto__);  //使用对象实例访问prototype指针;
	alert(Box.prototype);
	//使用构造函数(对象名)访问prototype  

    b、box.constructor

	Box.prototype.name='Lee';
	Box.prototype.age=21;
	Box.prototype.run=function(){
		return this.name+this.age+'运行中..';
	};
	var box=new Box();
	alert(box.constructor);
		//结果:function Box(){}
	alert(box.constructor==Object);		//false	
	alert(box.constructor==Box);		//true;


(2)使用字面量方式创建

其中的方括号就是创建了一个新对象

    a、创建一个原型对象

Box.prototype={
		name:'Lee';
		age:21;
		run:function(){
			return this.name+this.age+'运行中...';
		}
	};  

 

    b、重写prototype原型

重写后,之前的将不再存在,即覆盖

Box.prototype={
		age:22;   //这里不会保留之前的任何信息;
	
	};   

    c、box.prototype

	var box=new Box();
	//alert(box.run)
	alert(box.constructor==Object);  //true;  
        alert(box.constructor==Box);     //true;  

区别——

第一种构造函数的方法不可以指向Object,只能指向Box函数

第二种字面量方法既可以指向Box原型,又可以指向Object,(由于字面量花括号{}即表示的为新的     对象)


(2)通过原型prototype创建内置引用扩展(以sort排序为例)

      a、sort()最简单的排序——采用数组方式

	var box=[2,1,3,6,0,9];
	alert(box.sort());

结果:0 1 2 3 6 9


      b、查看sort是否为Array原型对象的方法

	alert(Array.prototype.sort);
	alert(String.prototype.substring); 

      c、内置引用类型扩展;

	String.prototype.addstring=function(){
		return this+'被添加了';
	};
	alert('Lee'.addstring());   //Lee被添加了;

    注意:不推荐用上述扩展对象办法,会导致命名冲突。


(3)原型优缺点

(1)即“共享”

(2)无法保持独立性

若引用类型时,添加或修改实例化都会发生冲突。


2、原型prototype

   (1)全部在原型prototype中定义函数

	function Box(){
	
	}


	Box.prototype={
		constructor:Box,
		name:'Lee',
		age:21,
		family:['哥哥','姐姐','妹妹'],
		run:function(){
			return this.name+this.age+'运行中';
		}
	};


	var box1=new Box();
	alert(box1.family);
	box1.family.push('弟弟');
	//在第一个实例修改后引用类型,保持了共享;


	var box2=new Box();
	alert(box2.family);
	//共享了box1添加后的引用类型的原型;

结果:(1)哥哥、姐姐、妹妹

      (2)哥哥、姐姐、妹妹、弟弟

      (3)哥哥、姐姐、妹妹、弟弟(共享)

上述案例中,由于原型的共享性,导致相互独立性与共享之间的属性无法区分开来,

为了解决这个问题,推荐使用混合模式,即“构造函数+原型模式”,见案例(2)


(2)构造函数+原型模式

要点:在共享的时候选择原型,在独立时选择构造函数;

分析:(1)由于name、age相对独立,使用构造函数模式

(2)run方法是一致的,采用原型共享的模式

	//1.保持独立的用构造函数
	function Box(name,age){
		this.name=name;
		this.age=age;
		this.family=['哥哥','姐姐','妹妹'];
	}
	//2.保持共享的用原型;
	Box.prototype={
		constructor:Box,
		run:function(){
			return this.name+this.age+'进行中';
		}
	};


	var box1=new Box('Lee',21);
	alert(box1.family);
	box1.family.push('弟弟');
	alert(box1.family);


	var box2=new Box('Jack',22);
	alert(box2.family);

结果:(1)哥哥、姐姐、妹妹
       (2)哥哥、姐姐、妹妹、弟弟
      (3)哥哥、姐姐、妹妹
    注意:(1)引用类型没有使用原型,所以没有共享;  

          (2)对于原型模式而言,不管是否调用了原型中的共享方法,他都会初始化原型中的方法,
最好的方式将原型与构造函数封装在一起,即“动态原型模式”,见案例(3)


(3)动态原型模式(封装)

    要点:a、将构造函数、原型模式封装在一起,实现了资源的高效性,同时减少内存;

          b、采用typeof关键字、if语句判断减少了初始化的次数,实现了效率的高效性。

//动态原型模式
function Box(name,age){
	this.name=name;
	this.age=age;
	this.family=['哥哥','姐姐','妹妹'];
	
	//判断this.run是否存在;
	if(typeof this.run!='function'){
		alert('原型初始化开始');
		Box.prototype.run=function(){
			return this.name+this.age+'运行中';
		};
		alert('原型初始化结束');
	}
	
}


//原型的初始化,只要第一次初始化即可,没必要每次多初始化,采用if语句判断;
var box1=new Box('Lee',10);


var box2=new Box('Jack',20);

结果:(1)原型初始化开始 原型初始化结束

      (2)原型初始化开始 原型初始化结束(只执行了两次)

注意:使用动态原型模式,注意不可以再用字面量方式重写原型,会切断实例和新原型之间的联系


(4)生构造模式=工厂模式+构造函数

工厂模式——即先创建一个对象object,再返回这个对象,同时为该对添加属性和方法;

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('Lee',21);
alert(box1.run());

  

(5)稳妥构造模式

与寄生构造模式唯一不同点是:稳妥构造模式不适用new关键字

 
  var box1=Box('Lee',21);
		alert(box1.run()); 

  

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值