之前看过一些关于原型的知识,但总是看了以后没有及时应用,导致再看到一些代码是遇到还是搞不清楚,借此机会谈一下我对prototype的理解。
1、再谈原型之前,我们要知道什么是构造器函数,型如下例:
function Car(){
this.wheels=5;
this.move=function(){
......
}
}
当然我们还遇到有其它格式的函数如:
命名函数:
function car(){
......
}
匿名函数(没有名字的函数):
var a=function(){
......
}
即时函数:
(function(){
... ...
})()
或者写成
(function(){
... ...
}())
2、再者,创建对象的方式有两种:
i:对象文本表示法,如下例:
var car={
wheel:5,
brand:'BMW',
move:function(){
alert('This car is mine');
}
}
II:通过构造器函数来创建对象,如下例:
function Car(name){
this.host=name,
this.brand='BMW',
this.wheel=4,
this.move=function(){
return 'This car belongs to'+this.name+'and it has'+this.wheel+'wheels'
}
}
然后用这个构造器函数来创建对象
var car=new Car('zhangsan');
>>car.name;
<<'zhangsan'
>>car.move();
<<This car belongs to zhangsan and it has 4 wheels
当我们创建对象的时候,同时也赋予了该对象一个特殊的属性--即构造器属性,该属性实际上指向了用于创建该对象的构造器函数的引用。例如上边创建的构造器函数
>>car.constructor;
<<function Car(name){
this.host=name,
this.brand='BMW',
this.wheel=4,
this.move=function(){
return 'This car belongs to'+this.name+'and it has'+this.wheel+'wheels'
}
}
当然,由于构造器属性所引用的是一个函数,因此我们可以利用它来创建一个其它的新对象。
>>var car2=new car.constructor('lisi');
>>car2.name;
<<'lisi'
3.接下来才进入到本篇的重点--原型prototype
I:每个函数的prototype都指向一个对象;
II:它只有在该函数是构造器时才发挥作用;
III:该函数所创建的对象都会持有一个该prototype属性的引用,并可以将其当做自身的属性来用。
举一个例子:
var people={
name:'xiaoming',
say:function(){
return 'I am a'+this.name;
}
}
function F(){
... ...
}
F.prototype=people;
//然后我们把F()当做一个构造器函数来创建对象foreigner,那么新的foreigner就会拥有对F.prototype属性(也就是foreigner)的访问权。
>>var foreigner=new F();
>>foreigner.name;
<<'xiaoming'
>>foreigner.say();
<<'I am a xiaoming;'
其实,说白了,对于一个构造函数的原型,也就是一个对象,然后你利用这个构造函数创建一个新对象,那么这个新对象就可以访问对象中的属性以及方法了。
4,那么在平时中我们都是怎样应用的呢?借助上边的例子继续说
I:利用原型添加方法和属性
function F(name,color){
this.name=name;
this.color=color;
this.what=function(){
return 'I am a'+this.color+''+this.name;
}
}
F.prototype.sex='male';
F.prototype.age=25;
F.prototype.info=function(){
return 'sex:'+this.sex+',age'+this.age;
}
//当然,你也可以定义一个对象然后覆盖到之前的原型上:
F.prototype={
sex:'male',
age:25,
info:function(){
return 'sex:'+this.sex+',age:'+this.age;
II:使用原型的方法和属性
>>var people=new F('liwu','red');
>>people.name;
<<'liwu'
>>people.what();
<<'I am a red liwu'
>>people.sex;
<<'male'
>>people.info();
<<'sex:male,age:25'
III:自身属性和原型属性以及如何判断它们
直白的说,位于构造器函数内部的属性是自身属性,位于原型中的属性属于原型属性
例如上边的例子中,name和color是自身属性,而sex和age都属于原型属性,那么当我们想访问获得原型中的属性对应的值时,JavaScript引擎会从自身属性查起,如果查不到,就会转到创建此对象的构造器函数的原型中进行查找,如果在原型中查到了该属性,就立即使用改属性的值。
比如:在自身属性和原型属性中有同名的属性,那么访问该对象的这个属性时,最终获得的是自身属性的值,而不是原型中这个属性的值,这也说明了JavaScript查询的顺序,同时也说明了自身属性的优先级高于原型属性。
5.判断一个对象是不是另一个对象的原型
I:每个对象都会有一个isPrototypeOf()的方法,用来判断一个对象是不是另外一个对象的原型
比如上边第3步中的例子
>>people.isPrototypeOf(foreigner);
<<true
II:大多数浏览器都支持ES5的Object.getPrototypeOf()方法
>>Object.getPrototypeOf(foreigner)==people;
<<true
III:神秘的_proto_链接
前边我们讲到当创建的对象在自身的属性中访问不到我们要找的那个属性时,相应的原型属性就会被纳入到查询范围。就好像其中有一个神秘的链接,指向了相关的原型对象。
在现代的JavaScript环境中,对象中确实存在一个指向相关原型的链接,这个神秘的链接就是_proto_属性,有时我们在浏览器调试的过程中,常常会看到它的身影
>>foreigner._proto_==people;
<<true
另外需要提醒的是_proto_和prototype并不是等价的,_proto_实际上是某个实例对象的属性,而prototype是属于构造器函数的属性。
>>typeof foreigner._proto_;
<<'object'
>>typeof foreigner.constructor.prototype;
<<'object'
基本上就介绍到这里吧,随后有新的体会,再继续补充。总觉得这个是你再进一步学习javascript的关键节点,应该学会。