JS中的原型

版权声明:起风了 https://blog.csdn.net/qq_29036809/article/details/85337549

原型模式

我们所创建的每个对象都有一个原型属性(prototype),该属性可以做到方法和属性。来看如下代码

	function EDG(player,score) {
		  this.player = ["scout","meiko","clearlove","iboy","scout"];
		  this.score = score;

		  this.Say = function (){
		  	alert("我们要夺冠");
		  }

	}
	var edg = new EDG();
	edg.Say();

如上述代码,此时会弹出弹框,我们会夺冠,因为edg是构造函数EDG的实例,而构造函数中又存在Say方法。
如果此时来了个新的战队EDG的2队(也就是新建一个EDG的构实例),他们的目标也是夺冠,那么他们也要读Say方法。

	//此时新来了一个战队EDG2
	//构造函数WE


    var edg2 = new EDG();
	edg2.Say();//我们要夺冠

有没有发现什么问题,edg2在创建实例的时候又重新创建了一遍Say方法,重复了,edg2里的say和edg里的是不一样的,独立的。

console.log(edg2.Say==edg.Say); //false

那么此时为了不重复要怎么办呢,第一种方法就是将Say定义在全局作用域里如下

    
    	//构造函数EDG
	function EDG(player,score) {
		  this.player = ["scout","meiko","clearlove","iboy","scout"];
		  this.score = score;

		  this.Say =Say;
		  

	}

	function Say(){
		alert("我们要夺冠");
	}

	var edg = new EDG();
	edg.Say();//我们要夺冠

	var edg2 = new EDG();
	edg2.Say();

	console.log(edg2.Say==edg.Say); //true
    

但是这样会造成代码污染。此时就需要用到第二种方法原型属性来共享方法和属性。如下代码

   function EDG(player,score) {
		  this.player = ["scout","meiko","clearlove","iboy","scout"];
		  this.score = score;

		  //将Say写入EDG的原型对象里,做到共享
		  EDG.prototype.Say =  function Say(){
		  	alert("我们要夺冠");
		  }

	}


	var edg = new EDG();
	edg.Say();//我们要夺冠

	var edg2 = new EDG();
	edg2.Say();

	console.log(edg2.Say==edg.Say); //true

与构造函数不同的是Say方法是写在原型里共享的,是同一个函数而不是各自又重新创建的。

理解原型对象

无论什么时候,只要创建一个新函数,就会创建一个对应的prototype的原型属性,这个原型属性默认指向函数的原型对象。
默认的原型对象里自动获得一个constructor的属性,这个属性包含一个指向prototype属性所在函数的指针,也就是指向函数,还拿EDG的例子来说, EDG.prototype.constructor指向EDG。

   function EDG(player,score) {
		  this.player = ["scout","meiko","clearlove","iboy","scout"];
		  this.score = score;

		  //将Say写入EDG的原型对象里,做到共享
		  EDG.prototype.Say =  function Say(){
		  	alert("我们要夺冠");
		  }

 }
//EDG.prototype.constructor指向EDG
 console.log(EDG.prototype.constructor == EDG);//true

当创建实例后,该实例内部会出现一个指向构造函数原型对象的指针,[[prototype]],虽然在js中没有标准的方式访问[[prototype]],但是在火狐,谷歌和Safari浏览器中提供了代替者,__ protp __,如果我们创建一个edg3的实例,此时
edg3.proto 指向 EDG.prototype


   function EDG(player,score) {
		  this.player = ["scout","meiko","clearlove","iboy","scout"];
		  this.score = score;

		  //将Say写入EDG的原型对象里,做到共享
		  EDG.prototype.Say =  function Say(){
		  	alert("我们要夺冠");
		  }

 }
//EDG.prototype.constructor指向EDG
 console.log(EDG.prototype.constructor == EDG);//true
 
//创建实例
 var edg3 = new EDG();

 console.log(edg3.__proto__ == EDG.prototype); //true

下面我们画张图来理解构造函数,实例和原型对象之间的关系(以构造函数EDG为例)

图为简单的原型关系

扫描二维码关注公众号,回复: 4700786 查看本文章

isPrototypeOf()方法

如图所示,实例和原型对象之间通过__proto__连接,它是[[prototype]]的替代,但实际上[[prototype]]是无法访问到的,但可以通过**isPrototype()**方法来确定实例和原型对象间是否有关。当实例对象和原型对象有关联的时候返回true。

 var ss = EDG.prototype.isPrototypeOf(edg3);
console.log(ss);//true,Y有关联

如果实例重新定义了属性或者方法呢?

当实例重新定义属性或方法时,会屏蔽原型中的属性和方法,并不会重写它,例如下列代码:

   function EDG(player,score) {
		
			  //将Say写入EDG的原型对象里,做到共享

		  EDG.prototype.player = ["scout","meiko","clearlove","iboy","scout"];
		  EDG.prototype.Say =  function Say(){
		  	alert("我们要夺冠");
		  }

 }

 var edg4 = new EDG();
 console.log(edg4.player);//"scout","meiko","clearlove","iboy","scout"

 var edg5 = new EDG();
 edg5.player = ["我是edg5的player"];
 console.log(edg5.player);//"我是edg5的player"

在EDG的实例edg5的player是自己的,而edg4的则是原型的,这是由于变量搜索原则,先在实例中找找到了就使用,找不到就接着去原型找,edg4中没有player所以就借用了原型对象的player

那么我们怎么删除实例的属性,可以使用delete删除实例属性。

 delete edg5.player;

判断一个属性是否存在于实例中——hasOwnProperty()

只有给定的对象存在于实例中才会返回true

   function EDG(player,score) {
		
			  //将Say写入EDG的原型对象里,做到共享

		  EDG.prototype.player = ["scout","meiko","clearlove","iboy","scout"];
		  EDG.prototype.Say =  function Say(){
		  	alert("我们要夺冠");
		  }

 }

 var edg4 = new EDG();
 var edg5 = new EDG();
 edg5.player = ["我是edg5的player"];
 console.log(edg4.player);//"scout","meiko","clearlove","iboy","scout"
 console.log(edg5.player);//"我是edg5的player"

console.log(edg4.hasOwnProperty("player"));//fasle
console.log(edg5.hasOwnProperty("player"));//true

猜你喜欢

转载自blog.csdn.net/qq_29036809/article/details/85337549
今日推荐