学习JavaScript有一段时间了,感觉原型那块儿又有点混乱了,现在写个笔记整理一下思路。
什么是原型
每创建一个函数,这个函数都会自带一个属性prototype指向一个原型对象,最初这个原型对象只包含一个属性constructor,这是指向我们创建的那个函数的指针。也就是说函数和原型对象分别通过prototype和constructor这两个属性(指针)能找到对方。
我们可以通过fn.prototype.propertyName=value来给原型对象继续添加属性和方法。这些属性和方法区别于在函数中书写的实例属性和方法。为什么会有这种区别或者说这种区别是怎么做到的呢?来看看创建一个实例后发生了什么。以下面的代码来说明:
function Person(name,age){
this.name=name,
this.age=age;
}
Person.prototype.hobby = ["running","swimming","tennis"];
Person.prototype.country="China";
Person.prototype.showName=function(){alert(this.name);};
var person1 = new Person("anna",10);
这里创建了一个实例person1,我们知道通过new方法创建的实例,原来Person中的this会被新创建的实例即person1取代,也就是说通过这样的方式,我们为对象person1增加了属性name和age,这些是person1自己所拥有的属性,独立于其他Person的实例,叫做实例属性。
同时,每创建一个实例,这个实例会自带一个内部属性[prototype],它是一个指向构造函数的原型对象的引用。也就是说person1对象其实现在包括了这么三个属性:
person1={
prototype:Person.prototype,
name:"anna",
age:10
}
这个内部属性一般来说是不可以通过脚本来访问到的,那它有什么用呢?在进行属性标识符查找的时候会用到它。
引擎在读到某个对象的属性时,会首先查找实例属性中有没有这个属性,如果有则停止,没有则通过内部属性[prototype]找到其关联的原型对象,看原型对象中有没有相应的属性。
实例属性和原型属性同名
这里需要注意,如果我们又为实例添加了一个和原型对象中同名的属性,或者说我们“重写”原型中的属性会发生什么。这得分属性是原始值类型还是引用类型。
- 原始类型
同名的实例属性会屏蔽掉原型对象中的同名属性,这里的屏蔽的意思是,这个属性变成了实例自己的实例属性了,跟原型对象中的属性半毛钱关系没有,它根本就不会“重写”原型对象中的属性,根本就是两个值,在内存中有两个空间。通过hasOwnProperty()可以看到已经成为自己的实例属性了:
person1.country="USA"; //重写属性
alert(person1.hasOwnProperty("country"));//true
可通过delete person1.country来删除实例属性,这样就又可以访问到原型对象中的属性了。
- 引用类型
而引用类型就不一样了,所有实例都共享原型对象中这个引用类型的属性,通过任何实例对引用类型数据进行的更改都是对同一个即原型对象中的这个属性进行更改,它不会像原始值类型属性一样通过”重写”的方式变成自己的实例属性:
person1.hobby.push("hiking");
alert(person1.hasOwnProperty("hobby"));//false
可看出通过hasOwnProperty来检测,发现重写后没有变成自己的实例属性。
问题:原型对象showName方法中的this是实例对象?解释为谁调用this就是谁?
由于时间关系先写到这儿,后面还会有补充。。。。
版权声明:本文为博主原创文章,未经博主允许不得转载。