javascript原型prototype

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>原型属性prototype</title>
<meta name="description" content="">
<meta name="keywords" content="">
<style type="text/css">
</style>
</head>
<body>
<script type="text/javascript">
//一、利用原型添加方法与属性
//1、创建一个构造器函数Gadget()
	function Gadget(name,color){
		this.name=name;
		this.color=color;
		this.whatAreYou=function(){
			return "I am a "+this.color+" "+this.name;
		};
	}
//2、为上面的构造器增加两个属性(price和rating)和方法(即getInfo())
	Gadget.prototype.price=100;
	Gadget.prototype.rating=3;
	Gadget.prototype.getInfo=function(){
		return 'Rating:'+this.rating+',price:'+this.price;
	};
//3、使用原型的方法与属性
	var newtoy=new Gadget('webcam','black');
	newtoy.name; //webcam
	newtoy.color;//black
	newtoy.whatAreYou();
	newtoy.price; //100
	newtoy.rating; //3
	newtoy.getInfo(); // Rating: 3,price: 100
/*4、由于在javascript中几乎所有对象都是通过传递引用的方式来传递的,
	因此、我们所创建的每个新对象实体中并没有一份属于自己原型副本。
	这也就意味着我们可以随时修改prototype属性,并且由同一构造器创建
	的所有对象的prototype属性也都会同时改变(甚至还会影响在修改之前就已经创建的那些对象)*/
	Gadget.prototype.get=function(what){
		return this[what];
	}
//即便newtoy对象在get()方法定义之前就已经被创建了,但我们依然可以在该对象中访问对象新增的方法
	newtoy.get('price'); //100
	newtoy.get('color'); //black
//二、自身属性与原型属性
	/*当我们访问newtoy的某个属性时,例如:newtoy.name时,javascript引擎会遍历该对象的所有属性,
	并查找出name属性。如果找到了就会立即返回其值。如果饿哦们访问rating属性时,javascript引擎依然会查询
	newtoy对象的所有属性,但是这一回它找不到一个叫rating的属性了。接下来,脚本引擎就会去查询用于创建当前
 	对象的构造器函数的原型(等价于我们直接访问newtoy.constructor.prototype)。如果在原型中找到了该属性,就
	立即使用该属性。
	  首先、我们知道每个对象都会有一个构造器,而原型本身也是一个对象,这意味着它必然也有一个构造器,
	  而这个构造器又会有自己的原型。于是这张结构可能会一直不断地持续下去,并最终取决于原型链的长度,
	  但其最后一环肯定是内建对象,因为它是最高级的父级对象。*/
//三、利用自身属性重写原型属性
	 // 1、对象自身的属性的优先级高于原型属性
		 Gadget.prototype.name='mirror';
	     var toy=new Gadget('camera');
		 toy.name; //camera
	 	 //通过hasOwnProperty()方法判断一个属性是自身属性还是原型属性
		 toy.hasOwnProperty('name');//true
	     //删除自身这个属性,同名的原型属性就会"浮出水面"
	     delete toy.name; //true
		 toy.name; //"mirror"
	     toy.hasOwnProperty('name'); //false
		 //我们可以随时重建这个自身属性:
		 toy.name='camera';
	     toy.name; //camera
	//2、hasOwnProperty()方法也可以判断某个原型属性是哪个原型对象的。
	 	toy.toString();  //[object Object]
		toy.hasOwnProperty('toString'); //false
		toy.constructor.hasOwnProperty("toString"); //false
		toy.constructor.prototype.hasOwnProperty("toString");//false
		Object.hasOwnProperty("toString");// false
		Object.prototype.hasOwnProperty("toString");//true
//四、枚举属性(使用for in)
	 	/*1、并不是所有的属性都会在for-in循环中显示。例如(数组的)length属性和constructor属性就不会被显示。
		那些会显示的属性被称为是可枚举的,我们可以通过各个对象所提供的propertyIsEnumerable()方法来判断
		对象的某个属性是否可枚举。
		2、原型链中的各个原型属性也会被显示出来,当然前提是它们是可枚举的。我们可以通过对象的
		hasOwnProperty()方法来判断一个属性是对象自身属性还是原型属性。
		3、对于所有的原型属性,propertyIsEnumerable()都会返回false,包括那些在for-in循环中可枚举的属性。*/
		newtoy=new Gadget('webcam','black');
		//propertyIsEnumerable()该方法会对所有的非内建对象返回true
		newtoy.propertyIsEnumerable('name'); //true
		//而对于內建属性和方法来说,它们大部分都是不可枚举的:
		newtoy.propertyIsEnumerable('constructor');// false
		//任何来自原型链中的属性也是不可枚举的
		newtoy.propertyIsEnumerable('price');//false
		//但是需要注意的是、如果propertyIsEnumerable()的调用是来自原型链上的某个对象
		//那么该对象中的属性是可以枚举的。
		newtoy.constructor.prototype.propertyIsEnumerable('price'); //true
//五、isPrototypeOf()方法
	//每个对象都会有一个isPrototypeOf()方法,这个方法会告诉我们当前对象是否是另一个对象
	//的原型
	var monkey={
		hair: true,
		feeds: 'bananas',
		breathes: 'air'
	};
	//创建Human()构造器,并将其原型属性设置为monkey
	function Human(name){
		this.name=name;
	}
	Human.prototype=monkey;
	var george=new Human('George');
	monkey.isPrototypeOf(george); //true
	//获得对象的原型:getPrototypeOf()方法
	Object.getPrototypeOf(george).feeds; //banana
	Object.getPrototypeOf(george)===monkey; //true
//六、_proto_链接
	//在现代javascript环境中,对象中确实存在一个指向相关原型的链接,
	//这个神秘的链接被叫做_proto_属性(proto这个词的两边各有两条下划线)
	var developer=new Human();
	developer.feeds="pizza";
	developer.hacks="javascript";
	developer._proto_===monkey; //true(在ie之类的浏览器中_proto_是不存在的)
	//_proto_与prototype并不是等价的。_proto_实际上是某个实例对象的属性,
	//而prototype则是属于构造器函数的属性。
	typeof developer._proto_;//object
	typeof developer.prototype;// undefined
	typeof developer.constructor.prototype; //object
//七、关于原型的总结
	/*
	* 1、在javascript中,所有函数都会拥有一个叫做prototype的属性,默认初始值
	* 为"空"对象(没有自身属性的对象)
	* 2、我们可以在相关的原型中添加新的方法和属性,甚至可以用自定义对象来完全
	* 替换掉原有的原型属性。
	* 3、当我们通过某个构造器函数来新建时(使用new操作符),这些对象就会自动拥有
	* 一个指向各自prototype属性的神秘链接,并且可以通过它来访问相关原型对象的
	* 属性。
	* 4、对象自身属性的优先级要高于其原型对象中的同名属性
	* 5、我们可以通过hasOwnPrototype()方法来区分对象自身属性和原型属性
	* 6、原型链的存在:如果我们在一个对象foo中访问一个并不存在的属性bar,
	* 即当我们访问foo.bar时,javascript引擎就会搜索该对象的原型的bar属性。
	* 如果依然没有找到bar属性,则会继续搜索其原型的原型,以此类推,知道搜索
	* 到Object.prototype。
	* 7、我们可以对內建的构造器函数进行扩展,以便所有的对象都能引用我们添加
	* 的功能。如果将某个函数赋值给Array.prototype.flip,所有的数组对象都能立即
	* 添加一个flip()方法,如[1,2,3].flip()。另外,在添加相关的方法和属性之前,
	* 应该做一些对已有方法的检测工作,这将会大大增加脚本对于未来环境的适应力
	*
	* 
	* */
</script>
</body>
</html>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啊哈前端

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值