原型与原型链
Nov 25, 2016简述
本文主要讲解 prototype, proto, constructor,instanceof各自的含义,构造函数,原型对象,实例之间的关系;描述出查找对象的属性的过程,原型链是如何构成的等等。
前言
每周一次的前端分享,想了几天实在是不知道分享啥,正好最近在看面向对象,那就讲讲原型和原型链吧,在我不理解它们的时候,每次面试只要听到这几个词就吓得半死,简直是前端的恶魔。学东西就是这样吧,越是不理解的越害怕以为很难,其实只要认真去学去理解,没有自己想象的那么难。还是那句话,不懂的总有一天会懂,共勉。
原型
原型(prototype)
原型(prototype):当一个函数被声明时,该函数下默认有一个属性:prototype,该属性的值是一个对象,当我们调用一个对象的属性或者方法的时候,如果该对象自身没有该属性或者方法,则会调用到该对象构造函数下的prototype的属性和方法。
简言之,prototype是声明一个函数的时候,在该函数下js创建的一个属性,这个属性指向函数的原型对象。
prototype的使用:通过某个构造函数创建出来的对象都可以公用的属性和方法。
code::
function AA(){};
var a = new AA();
console.log(AA.prototype); //Object,只有function定义的对象有该属性
console.log(a.prototype); //undefined,new操作符生成的对象没有该属性
constructor
constructor(构造函数):默认情况下,所有的原型对象都会自动获得一个constructor
属性,这个属性包含一个指向prototype属性所在函数的指针。
code:
输出结果:
proto
proto:当调用构造函
数创建一个新实例后,该实例的内部将包含一个指针(内部属性[[prototype]]),指向构造函数的原型对象。在ECMA-262第五版中这个指针叫做[[prototype]]。
虽然在脚本中没有标准的方式访问[[prototype]],但浏览器在每个对象上都支持一个属性
proto;而在其他实现中,该属性对脚本完全是不可见的。
栗子:

输出结果:
构造函数、原型对象、实例之间的关系
栗子:

解释:声明了一个构造函数Person,则该构造函数下会自动创建一个prototype属性;手动的给Person.prototype加上了name,sex,action等属性;实例化new Person(),生成实例对
象p1;实例对象p1的proto指向了Person的原型对象,而Person的原型对象的constructor指向了构造函数Person,但是Person构造函数的prototype又指回了Person的原型对象。
换句话说,实例和构造函数没有直接关系;这个连接存在与实例和构造函数的原型对象之间。因此:Person.prototype === p1.proto.
详细描述图:
查找对象的属性
当代码读取某个对象的某个属性的时候,都会执行一次搜索,目标是具有给定名字的属性,搜索首先会从对象实例本身开始。如果在实例中找到了给定名字的属性,则返回该属性的值;如果没有找到,则继续搜索指针指向的原型对象。
实例属性和原型属性
1)code:

在实例中添加一个属性,而该属性与实例原型中的一个属性同名,我们就在实例中创造该属性,而屏蔽原型中的该属性(阻止我们访问原型中的那个属性,而不会修改那个属性)。虽然我们可以通过实例访问保持在原型中的值,但却不能通过对象实例重写原型中的值。
2)code:
即使将p1.name设置为null,也只会在实例中设置这个属性,而不会恢复其指向原型的连接。只有通过delete操作符删除实例属性,才能够重新访问原型中的属性。
效果如:
判断属性存在原型上还是实例上
hasOwnPrototype():只在给定属性存在对象实例中,才会返回true。
in操作符:它会在通过对象能够访问给定属性时返回true,无论该属性存在于实例中还是原型中。
方法:
function hasPrototypeProperty(object, name){
return !object.hasOwnPrototype(name) && (name in object);
}
原型链
原型对象也是普通的对象,并且也有可能有自己的原型,如果一个原型对象的原型不为null的话,我们就称之为原型链(prototype chain)
理解了下面两图的内容差不多就理解了原型链。

