JavaScript深入理解之原型与原型链

写在前面
原型和原型链一直都是中很重要的概念 , 理解它们有助于我们理解预定义引用类型间的关系以及中对象继承的实现机制 , 下面是我对原型和原型链的理解和总结 。
原型 原型对象理解
函数对象的属性
我们创建的每一个函数都有一个属性 , 这个属性是一个指针 , 指向一个对象 。这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法 , 简单来说 , 该函数实例化的所有对象的的属性指向这个对象 , 它是该函数所有实例化对象的原型 。
function Person(){}// 为原型对象添加方法Person.prototype.sayName = function(){ alert(this.name);}
下面我们来看一下它们之间的关系 。
属性
当函数创建 ,  属性指向一个原型对象时 , 在默认情况下 , 这个原型对象将会获得一个属性 , 这个属性是一个指针 , 指向所在的函数对象 。
拿前面的一个例子来说 .. 就指向函数对象 。
下面我们来更新一下它们之间的关系图 。
对象的属性
当我们调用构造函数创建一个新实例后 , 在这个实例的内部将包含一个指针 , 指向构造函数的原型对象 , 在 ECMA-262 第五版中管这个指针叫做 [[]]。所有的对象都含有 [[]] 属性 , 指向它们的原型对象 , 这是理解原型链的一个关键概念 。
需要注意的是在脚本中没有标准的方式访问 [[]] 属性 , 但是在  ,  和中每个对象中都支持一个属性来访问 , 为了区分属性 , 我们在下边都使用 来表示 。
根据前面的构造函数我们新建一个实例
var student = new Person();console.log(student.__proto__ === Person.prototype); // true
从上面我们可以看出 , 这个连接是存在与实例与构造函数的原型对象之间的 , 而不是存在于实例和构造函数之间的 。
下面我们来看一下现在这几个对象之间的关系
()
虽然我们在脚本中没有办法访问到[[]]属性 , 但是我们可以通过方法来确定对象之间是否存在这种关系 。

JavaScript深入理解之原型与原型链

文章插图
() 方法用于测试一个对象是否存在于另一个对象的原型链上 。
console.log(Person.prototype.isPrototypeOf(student)); // true
.()
在5 中新增了一个方法叫 .()  , 这个方法可以返回[[]]的值 , 如下???????
console.log(Object.getPrototypeOf(student) === Person.prototype); // true
原型属性
属性访问
每当代码读取对象的某个属性时 , 首先会在对象本身搜索这个属性 , 如果找到该属性就返回该属性的值 , 如果没有找到 , 则继续搜索该对象对应的原型对象 , 以此类推下去 。
因为这样的搜索过程 , 因此我们如果在实例中添加一个属性时 , 这个属性就会屏蔽原型对象中保存的同名属性 , 因为在实例中搜索到该属性后就不会再向后搜索了 。
属性判断
既然一个属性既可能是实例本身的 , 也有可能是其原型对象的 , 那么我们该如何来判断呢?
在属性确认存在的情况下 , 我们可以使用 () 方法来判断一个属性是存在与实例中 , 还是存在于原型中 。注意这个方法只有在给定属性存在于实例中时 , 才会返回 true。