深入javascript之原型和原型链

我们知道在js中,万物皆对象,对象可以说是重中之重了。每一个对象都拥有自己的属性。但是在这个世界中有很多东西都是相似的,可以归为一类,他们有共同的方法和属性。不可能让每一个对象都定义一个属性吧。那样太消耗内存了。所以,在js中怎么才能让多个对象共享一个或多个方法呢?原型的出现就是为了解决这个问题。

在js中每个对象都有一个与它关联的对象,叫做原型对象。每一次获取对象属性都是一次查询过程,当在对象的自有属性中找不到时就会去查找它的原型对象。

在js中函数也是一个对象。每个函数都有一个prototype属性(只有函数才有prototype属性),这是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。按照字面意思来理解,那么prototype就是通过调用构造函数而创建的那个对象实例的原型对象。其中原型对象会自动获得一个constructor属性,这个属性指向prototype属性所在的指针。如下面的Man.prototype.constructor指向Man。

function Man(name,age) {
this.name = name;
this.age = age;
}
function test() {
var person1 = new Man("张三","18");
var person2 = new Man("李四","19");
Man.prototype.sex = "男";
console.log(person1.sex); //男
console.log(person2.sex); //男
}

每个男孩共有的属性就是他的性别都是男,所以我们可以将此属性添加到实例的原型对象中去。这样每个实例都可以共享这个属性。

我们前面说了每个函数都有prototype属性,指向函数的原型对象。他的实例对象可以共享这个属性,那我们怎么将实例对象和原型对象关联起来呢?在js中,任何对象都有一个属性叫proto([[prototype]]),它也是一个指针,指向构造函数的原型对象,就是我们所能共享信息的那个对象。现在我们可以画出一幅图,展示他们之间的关系。

注意: 理解对象的原型(可以通过Object.getPrototypeOf(obj)或者已被弃用的proto属性获得)与构造函数的prototype属性之间的区别是很重要的。前者是每个实例上都有的属性,后者是构造函数的属性。也就是说,Object.getPrototypeOf(new Foobar())Foobar.prototype指向着同一个对象。

原型

原型链是什么呢,根据字面意思我们可以这样理解,就是将原型连成一条链。我们上面讲过,js每一次获取对象中的属性都是一次查询过程,如果在自有属性中找不到就会去原型对象中查找,如果原型对象中还查不到,就回去原型对象的原型中查找,也就是按照原型链查找,直到查找到原型链的顶端,也就是Object的原型。

function FutherType(){
this.property = true;
}
FutherType.prototype.getFutherValue - function(){
return this.property;
}
function SonType(){
this.sonproperty = false;
}
SonType.prototype = new FutherType();
SonType.prototype.getSonValue = function(){
return this.sonproperty;
}
var instance = new SonType();
console.log(instance.getFutherValue()); //true

原型对象之间的关系如下图:

原型对象