js的prototype--js详解(十三)

1、js原型讲解

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
	/**
	 * 原型是js中非常特殊一个对象,当一个函数创建之后,会随之就产生一个原型对象
	 * 当通过这个函数的构造函数创建了一个具体的对象之后,在这个具体的对象中
	 * 就会有一个属性指向原型
	 */
	//第一种状态
	function Person(){
		
	}
	//第二种状态
	Person.prototype.name = "Leon";
	Person.prototype.age = 23;
	Person.prototype.say = function() {
		alert(this.name+","+this.age);
	}
	//第三中状态,创建了一个对象之后会有一个_prop_的属性指向原型
	//在使用时如果在对象内部没有找到属性会去原型中找,_prop_属性是隐藏的
	var p1 = new Person();
	//p1.say();
	//以下方法可以检测出p1是否有_prop_指向Person的原型
	//alert(Person.prototype.isPrototypeOf(p1));
	
	//第四种状态
	var p2 = new Person();
	//是在自己的空间中定义了一个属性,不会替换原型中的属性
	p2.name = "Ada";
	//p2.say();
	//p1.say();
	
	// //检测某个对象是否是某个函数的原型
	// alert(Person.prototype.isPrototypeOf(p2));
	
	// //检测某个对象的constructor
	// alert(p1.constructor==Person);
	
	// //检测某个属性是否是自己的属性
	// alert(p1.hasOwnProperty("name"));//false,p1自己的空间中没有值
	// alert(p2.hasOwnProperty("name"));//true,p2在自己的空间中设置了name属性
	
	//delete p2.name;
	//p2.say();
	//alert(p2.hasOwnProperty("name"));//由于已经删除了,所以是false
	
	//检测某个对象在原型或者自己中是否包含有某个属性,通过in检测
	//alert("name" in p1);//true
	//alert("name" in p2);//true
	//alert("address" in p1);//在原型和自己的空间中都没有,false
	
	alert(hasPrototypeProperty(p1,"name"));//true
	alert(hasPrototypeProperty(p2,"name"));//false
	/**
	 * 可以通过如下方法检测某个属性是否在原型中存在
	 */
	function hasPrototypeProperty(obj,prop) {
		return ((!obj.hasOwnProperty(prop))&&(prop in obj))
	}
	</script>
</head>
<body>
</body>
</html>

以下是内存模型图

 

2、使用json格式创建原型

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
	/**
	 * 原型是js中非常特殊一个对象,当一个函数创建之后,会随之就产生一个原型对象
	 * 当通过这个函数的构造函数创建了一个具体的对象之后,在这个具体的对象中
	 * 就会有一个属性指向原型
	 */
	//第一种状态
	function Person(){
		
	}
/**
 *使用如下方式来编写代码,当属性和方法特别多时,编写起来不是很方便,可以通过json的格式
 * 来编写 
 */
	// Person.prototype.name = "Leon";
	// Person.prototype.age = 23;
	// Person.prototype.say = function() {
		// alert(this.name+","+this.age);
	// }
	/**
	 * 以下方式将会重写原型
	 * 由于原型重写,而且没有通过Person.prototype来指定
	 * 此时的constructor不会再指向Person而是指向Object
	 * 如果constructor真的比较重要,可以在json中说明原型的指向
	 */
	Person.prototype = {
		constructor:Person,//手动指定constructor
		name:"Leon",
		age:23,
		say:function() {
			alert(this.name+","+this.age);
		}
	}
	var p1 = new Person();
	p1.say();
	alert(p1.constructor==Person);
	</script>
</head>
<body>
</body>
</html>

 3、使用json创建的问题

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
	/**
	 * 原型是js中非常特殊一个对象,当一个函数创建之后,会随之就产生一个原型对象
	 * 当通过这个函数的构造函数创建了一个具体的对象之后,在这个具体的对象中
	 * 就会有一个属性指向原型
	 */
	//第一种状态
	function Person(){
		
	}
	
	var p1 = new Person();
	Person.prototype.sayHi = function() {
		alert(this.name+":hi");
	}
	
	/**
	 *如果把重写放置在new Person之后,注意内存模型,原型重写的问题
	 */
	Person.prototype = {
		constructor:Person,//手动指定constructor
		name:"Leon",
		age:23,
		say:function() {
			alert(this.name+","+this.age);
		}
	}
	
	p1.sayHi();//不会报错,但是没有this.name
	
	var p2 = new Person();
	//p2.sayHi();//此时p2没有sayHi,所以就会报错
	p2.say();
	p1.say();	//此时p1没有say方法,所以就会报错:Uncaught TypeError: undefined is not a function
	</script>
</head>
<body>
</body>
</html>

 4、原型创建对象所带来的问题

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
	/**
	 *基于原型的创建虽然可以有效的完成封装,但是依然有一些问题
	 * 1、无法通过构造函数来设置属性值
	 * 2、当属性中有引用类型变量是,可能存在变量值重复
	 */
	function Person(){
		
	}
	Person.prototype = {
		constructor:Person,
		name:"Leon",
		age:30,
		friends:["Ada","Chris"],
		say:function() {
			alert(this.name+"["+this.friends+"]");
		}
	}
	var p1 = new Person();
	p1.name = "John";
	p1.say();//john[ada,chris]
	//会在原型中找friends,所以Mike是在原型中增加的
	p1.friends.push("Mike");//为p1增加了一个朋友
	var p2 = new Person();
	//此时原型中就多了一个Mike,这就是原型所带来的第二个问题
	p2.say();//leon ada chris mike
	</script>
</head>
<body>
</body>
</html>

 5、通过组合构造函数和原型来实现对象的创建,来解决原型所带来的问题

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
/**
 * 为了解决原型所带来的问题,此处需要通过组合构造函数和原型来实现对象的创建
 * 将属性在构造函数中定义,将方法在原型中定义
 * 这种有效集合了两者的优点,是目前最为常用的一种方式
 */
	function Person(name,age,friends){
		//属性在构造函数中定义
		this.name = name;
		this.age = age;
		this.friends = friends;
	}
	Person.prototype = {
		constructor:Person,
		//方法在原型中定义
		say:function() {
			alert(this.name+"["+this.friends+"]");
		}
	}
	//此时所以的属性都是保存在自己的空间中的
	var p1 = new Person("Leon",23,["Ada","Chris"]);
	p1.name = "John";
	p1.friends.push("Mike");//为p1增加了一个朋友
	p1.say();
	var p2 = new Person("Ada",33,["Leon"]);
	p2.say();//leon
	</script>
</head>
<body>
</body>
</html>

 6、动态页面原型

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
/**
 * 为了让定义的方式更加符合java的需求,就把定义方法的原型代码放置到Person这个构造函数中
 */
	function Person(name,age,friends){
		//属性在构造函数中定义
		this.name = name;
		this.age = age;
		this.friends = friends;
		
		//不能使用重写的方式定义
		/*Person.prototype = {
			constructor:Person,
			//方法在原型中定义
			say:function() {
				alert(this.name+"["+this.friends+"]");
			}
		}*/
		/**
		 * 判断Person.prototype.say是否存在,如果不存在就表示需要创建
		 * 当存在之后就不会在创建了
		 */
		if(!Person.prototype.say) {
			Person.prototype.say = function() {
				alert(this.name+"["+this.friends+"]");
			}	
		}
	}
	
	//此时所以的属性都是保存在自己的空间中的
	var p1 = new Person("Leon",23,["Ada","Chris"]);
	p1.name = "John";
	p1.friends.push("Mike");//为p1增加了一个朋友
	p1.say();
	var p2 = new Person("Ada",33,["Leon"]);
	p2.say();//leon
	</script>
</head>
<body>
</body>
</html>

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值