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

 ECMAScript有两种开发模式:1、函数化;2、面向对象(OOP),

     面向对象有一个标志,即“类”,通过类可以创建任意多个具有相同属性和方法的对象。

  但是,ECMASctipt没有类的概念,因此它的对象也与基于类的对象有所不同。


1、创建对象

案例1-1——对象的使用以及this关键字:

	var box=new Object();
	box.name1='Lee';
	box.age=10;
	box.run=function(){
		return this.name+this.age+'运行中...';   //this表示当前作用域下的对象;
	};
	//this表示new Object()实例化出来的对象;
	//this要放在一个作用域中,比如box.run(){},只是box作用域下的方法,即可用this来表示box
	alert(box.run());   
	var name1='Jack';
	alert(this.name1);   //此时this表示window对象


结果:(1)Lee 10 运行中...

      (2)Jack(由于作为了全局变量,取代了之前的name1)


案例1-2——解决实例化对象产生重复的方法(工厂模式)

//工厂模式
	function createObject(name,age){
		var obj=new Object();   //创建对象;
		obj.name=name; 		//为对象添加属性
		obj.age=age;		
		obj.run=function(){	//为对象添加方法;
			return this.name+this.age+'运行中...';
		};
		return obj.;		//返回obj这个对象的引用;
	};
	var box1=createObject('Zhao',21);    //创建第一个、第二个对象;
	var box2=createObject('Zhang',20);

	alert(box1.run());		//打印出第一个、第二个对象的实例化run()方法;
	alert(box2.run());

	alert(box1 instanceof Object);   //true;
	alert(box2 instanceof Object);	//true;


注意:由于上述若有重复的createObject2()方法,内容与第一个完全相同,且有一个box3对象,

并把它实例化,会发现在box3 instanceof Object时,也会返回true,并不能准确判断哪个实例化方法,

为此,可采用构造函数方法,即案例1-3。


案例1-3——构造函数:既解决了重复实例化的问题,又解决了对象识别的问题,并没有new Object(),却可以实例化Box()

	function Box(name,age){		//创建一个对象,所有构造函数的对象其实都是Object
		this.name=name;		//添加一个属性
		this.age=age;
		this.run=function(){	//添加一个方法;
			return this.name+this.age+'运行中';
		};
	};
	
	function Dock(name,age){		//创建一个对象,所有构造函数的对象其实都是Object
		this.name=name;		//添加一个属性
		this.age=age;
		this.run=function(){	//添加一个方法;
			return this.name+this.age+'运行中';
		};
	};
	var box1=new Box('Zhao,21');	//实例化;
	var box2=new Box('Zhang,20');
	var box3=new Dock('Huang,22');
	//alert(box1.run());
	//alert(box2.run());
	alert(box1 instanceof Box);    //true;
	alert(box3 instanceof Box);	//false;


解析:由于在上述函数中,构造了两个函数,若要用instanceof测试对象,即可以发现

box1是Box的实例化对象,所以返回true;box3是Dock的实例化对象,不是Box的

实例化对象,所以返回了false;


区别——构造函数、工厂模式

(1)构造函数没有显示的创建对象(new Object())

(2)直接将属性和方法赋值给this对象

(3)没有return语句;

(new Object()相当于直接在后台上创建了对象方法)


案例1-4——this的使用(全局访问name会有干扰)

	function Box(user,age){
		this.user=name;
		this.age=age;
		this.run=function(){
			return this.user+this.age+'运行中...';
		};
	};
	var box1=new Box('Zhao',21);
	alert(box1.run());   //Zhao 21 运行中...
	alert(this.name);
	//由于该this指向的是window对象,为null,即返回“unfined”


案例1-5——对象冒充call()方法

	//...构造函数
	var o=new Object();
	box.call(o,'Zhao',21);   //对象冒充
	alert(o.run());


案例1-6——属性、方法、地址的比较

	var box1=new Box('Zhao',21);
	var box2=new Box('Zhao',21);
	alert(box1.age==box2.age);       //true;
	alert(box1.run()==box2.run());   //true;
	alert(box1.run==box2.run);       //false;


解析:由于在进行box.run比较时,比较的是地址,

box1对象实例化对应的是地址1,box2对象实例化对应的是地址2,所以二者不相等

(比较的是引用地址) 

总结:对于一个对象,其属性和方法对于一个相等传递参数均相等,但对于实例化地址而言,是不相等的。


2、原型

由于创建的每一个函数都有prototype(原型)属性,这个属性是一个对象。

(1)用途:包含可以由特定类型的所有实例共享的属性和方法

简而言之,prototype通过调用构造函数而创建的那个对象的原型对象。

(2)优点:可以让所有对象实例共享它包含的属性和方法,即不必在构造函数中定义对象信息,

    而是可以直接将这些信息添加到原型中。

案例2-1——原型prototype构造函数

	functionc Box(){
	....
	};

解析:当构造函数体内有东西(属性/方法),即叫做实例属性、实例方法

	Box.prototype.name='Zhao';
	Box.prototype.age=21;
	Box.prototype.run=function(){
		return this.name+this.age+'运行中...';
	};
	var box1=new Box();
	var box2=new Box();
	alert(box1.run());		//Zhao 21 运行中;     
	alert(box1.run==box2.run);   //true 


区别——实例化构造与原型prototype构造函数

最大的不同点,即原型prototype构造函数时,会共享地址,

在进行box.run比较时,返回true,共享了同一个地址

(1)实例化构造函数,box1,box2均为function类型,但二者相互独立;

(2)原型prototype构造函数,box1,box2均会指向原型对象的一个_proto_属性(指针),当实例化了该指针属性时,

它的作用是指向构造函数的原型属性constructor。

案例2-1(2)——prototype

alert(box1.prototype);   //由于prototype是一个对象,所以访问不到

注意:在IE浏览器不能识别


案例2-2——判断原型prototype是否存在

	var obj=new Object();
	alert(Box.prototype.isPrototypeOf(obj));    //只要实例化对象,就会指向原型


(3)原型模式的执行流程

a、先查找构造函数实例里的属性或方法,若有,即返回;

b、若构造函数中没有,则去它的原型对象中找,若有,就返回。

案例2-3——虽说可以通过对象实例访问保存在原型中的值,但不可以访问通过对象实例重写原型中的值。

	var box1=new Box();
	alert(box1.name);      //Zhao,由于在案例2-1时,Box.prototype.name='Zhao',原型中的值;
	box1.name='Zhang';
	alert(box1.name);      //Zhang,就近原则
	var box2=new Box();
	alert(box2.name);	//Zhao,原型中的值,没有被box1修改


案例2-4——若想在就近原则后访问原型属性,即可以先删除实例中属性delete

	delete box1.name;
	alert(box1.name);     //删除了就近原则时的Zhang,可返回原型中的Zhao


(4)a、判断实例中是否存在指定属性hasOwnProperty()

     b、in操作符,会在通过对象能够访问给定属性时访问true,无论该属性在实例中还是在原型中

    (in操作符表示只要有就返回true


案例2-5——判断实例中是否有指定属性

	function Box(){}    //构造函数为空
	Box.prototype.name='Zhao';
	Box.prototype.age=21;
	Box.prototype.run=function(){
		return this.name+this.age+'运行中...';
	};
	var box1=new Box();   //表示实例化了Box()
	box1.name='Zhang';
	alert(box1.hasOwnProperty('name'));  //由于实例了name->'Zhang',所以结果应该返回true


案例2-5——in操作符的使用

     上述代码修改为

	var box1=new Box();
	alert('name' in box1);
 //不管实例或原型属性是否存在,只要有就会返回true;两边都没有,返回flase。


案例2-6——判断原型中是否有属性

(将案例2-5与案例2-6合并起来)

	function isProperty(object,property){
		return !object.hasOwnProperty(property)&&(property in object);
		//表示实例中没有,原型和实例中都有,即“只有原型中有”
	}
	
	//原型
	function Box(){...}
	Box.prototype.name='Zhao';   //原型属性;
	Box.prototype.age=21;
	var box1=new Box();    
	//box1.name='';		//实例属性;
	//alert(isProperty(box1,'name'));  //false,由于在实例化对象属性中仍有,返回false;

	alert(isProperty(box1,'name'));    //true
	//由于在实例中创建的box1对象没有name,但在原型中有,所以返回true;



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值