论坛首页 Web前端技术论坛

javascript 原型函数 prototype 工作原理

浏览 10446 次
精华帖 (0) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (1)
作者 正文
   发表时间:2011-11-10  
Javascript 中的原型函数(prototype)的工作原理,在 javascript 中每次声明新函数的过程中,就会为其创建一个 prototype 的属性。在未加其他附带条件情况下,所有的 prototype 属性都会自动获取 constractor 属性,constructor 内包含一个指向 prototype 属性所属函数的指针(就是说 constructor 回指构造函数本身)。

举个例子来说,Fruit.prototype.constructor 指向 Fruit。并且可以通过这个构造函数,为其添加更多的属性和方法。

当调用构造函数创建一个新实例后,该实例内部包含一个指针指向构造函数的原型函数。此时我们不用去关心内部的这个指针到底是什么(这个指针还的确有个名字:__proto__ 估计是为了对应 prototype 而起的名字吧 ~\(≧▽≦)/~ ),只需记住它的指向即可(指向构造函数的原型函数)。需要注意的是,这个 __proto__ 只存在于函数实例与构造函数的原型函数之间,而非实例与构造函数之间。

下面画个图,来精心诠释一下。



如上图所示,Fruit_1, Fruit_2 与构造函数没有直接的联系,只是这两个实例的 __proto__ 属性指向了 Fruit.prototype。虽然这两个实例都不包含属性和方法,但却可以通过 fruit_1.showPrice() 来调用。其理论依据是通过查找对象属性的过程来实现的。

举个例子来说:

       function Fruit(){
       }
	
       Fruit.prototype.category = "apple";
       Fruit.prototype.price = 19.9;
       Fruit.prototype.showPrice = function(){
           alert(this.price); 
       }
	
       var fruit_1 = new Fruit();
       var fruit_2 = new Fruit();
       alert(fruit_1.constructor == fruit_2.constructor);  // 输出 true
       fruit_1.showPrice(); // 19.9


此时,Fruit()构造函数变成了一个空函数,但却可以通过调用 prototype 往构造函数内直接增加属性和方法。并且在此时,仍然可以调用构造函数来 new 新对象,并且新对象具有通过原型函数向构造函数直接增加的属性和方法(有点拗口啊,就是说,通过原型函数直接向构造函数增加属性和方法,增加的这些属性和方法,在通过构造函数 new 出来新实例中也具有)。

并且通过上面的例子可以看出,通过构造函数 new 出来的不同对象,具有与构造函数相同的属性和方法。并且这些都是共有的。

这一切的一切表明,在构造函数外部可以通过原型函数为其增加属性和方法,并且与在构造函数内部声明具有相同的效果。
  • 大小: 98.9 KB
   发表时间:2011-11-11   最后修改:2011-11-15
上述代码是在构造函数内部没有成员属性和成员函数的情况下,如果构造函数内存在成员属性或成员函数,则变量首先去检索具有给定名字的对象的成员函数,如果存在则执行成员函数,如果不存在,则继续向前检索原型函数。

犹如这条检索链:对象 -> 实例函数属性或方法 -> (若没有找到)则检索原型函数。

下面一个例子很好的说明了这一点:

            function Fruit(){
		  this.showPrice = showPrice;
	    }
			
	    function showPrice(){
		   alert("100000");
	    }
	
            Fruit.prototype.category = "apple";
	    Fruit.prototype.price = 19.9;
	    Fruit.prototype.showPrice = function(){
		  alert(this.price); 
	    }
			
            var fruit_1 = new Fruit();
	    var fruit_2 = new Fruit();
	    fruit_1.showPrice(); // 100000


输出为100000,则正面首先从构造函数去检索,检索到了之后就不再去执行原型函数了,但如果按照 javascript 解释性语言来解释的话,输出就应该是 19.9 了。
0 请登录后投票
   发表时间:2011-11-11  
如果这么说的话
Fruit.prototype.constructor=People.prototype.constructor;
新定义一个function,这样再创建Fruit实例,按上面说的话应该不会再指向Fruit的构造函数了吧??
0 请登录后投票
   发表时间:2011-11-11   最后修改:2011-11-11
lz12366 写道
如果这么说的话
Fruit.prototype.constructor=People.prototype.constructor;
新定义一个function,这样再创建Fruit实例,按上面说的话应该不会再指向Fruit的构造函数了吧??

上述为指针赋值,就像“光棍节”与“11月11号”一样,是对同一个日子不同的称呼,
Fruit.prototype.constructor=People.prototype.constructor = "&构造函数";
那么下面的说法应该没错吧:
Fruit实例的构造函数是 "&构造函数",People实例的构造函数是"&构造函数"。
0 请登录后投票
   发表时间:2011-11-12  
泰山宏图 写道
lz12366 写道
如果这么说的话
Fruit.prototype.constructor=People.prototype.constructor;
新定义一个function,这样再创建Fruit实例,按上面说的话应该不会再指向Fruit的构造函数了吧??

上述为指针赋值,就像“光棍节”与“11月11号”一样,是对同一个日子不同的称呼,
Fruit.prototype.constructor=People.prototype.constructor = "&构造函数";
那么下面的说法应该没错吧:
Fruit实例的构造函数是 "&构造函数",People实例的构造函数是"&构造函数"。


是这个意思。
但是在使用 prototype 的时候一共有两种方法,一种方法就如上面所示,Fruit.prototype.xxx = "xxx";就可以。
第二种是通过字面量来声明的,即

function Fruit(){
		}
			
Fruit.prototype = {
	category :"apple" ,
	price : 19.9 ,
	showPrice : function(){
		alert(price);
		}
	}
			
var fruit = new Fruit();
alert(fruit.constructor == Fruit); // false
alert(fruit.constructor == Object); // true


很奇怪的一点是,fruit.constructor == Fruit() 的输出false,不再是 true 了。这是因为本质上我们已经重写了默认的 prototype 对象,因此 constructor 属性所指向的内容也就变成了新对象的 constructor 属性,而这个属性指向的是 Object 构造函数。

可以通过增加一句话来定义 constructor。

function Fruit(){
		}
			
Fruit.prototype = {
	constructor:Fruit ,
	category :"apple" ,
	price : 19.9 ,
	showPrice : function(){
		alert(price);
		}
	}
			
var fruit = new Fruit();
alert(fruit.constructor == Fruit); // true
alert(fruit.constructor == Object); //false

显示的声明 constructor 就可以让它知道所指的构造函数。
0 请登录后投票
   发表时间:2011-11-14  
讲得不错。可以再讲下基于原型的类继承。
0 请登录后投票
   发表时间:2011-11-14  
写的不错,一看楼主就花了很大精力,支持!
0 请登录后投票
   发表时间:2011-11-15  
楼主的贴子废话特别多,本来简单的例子,被楼主一大堆废话说出来,简单的都变复杂了,绝对是误人子弟的贴
0 请登录后投票
   发表时间:2011-11-15   最后修改:2011-11-15
mfkvfn 写道
讲得不错。可以再讲下基于原型的类继承。


好的,没问题,我新开了一个帖子来说明。

由 OO 继承来谈谈 javascript 继承
0 请登录后投票
   发表时间:2011-11-15  
不看懂        
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics