How to travel in time? read. How to feel time? Write.
前几天仔细的看了看javascript的原型模式和基于原型的继承, 今天就对其作一个简单的总结作为读书笔记。
什么是原型
function Person() {
}
Person.prototype.name = 'Scofiled';
Person.prototype.age = 29;
Person.prottype.sayName = function() {
return this.name;
}
var person1 = new Person();
person1.sayName(); // 'Scofield'
alert(person1.age); //29
var person2 = new Person();
person2.sayName(); // 'Scofield'
alert(person2.age); //29
这里定义了一个名为Person
的函数,然后在在它的prototype
属性上又添加了如上几个属性。 然后创建了Person
的两个实例。
这个prototype
是哪里来的呢? 我们每创建一个新函数, 就会自动为该函数创建一个prototype
属性,这个属性指向一个对象,这个对象就是原型对象。
原型对象是拿来干嘛的?如上面代码显示的,person1
和person2
都是Person
的实例, 这两个实例都具有了Person.prototype
上定义的属性和方法。简而言之,原型对象的用途就是让某特定类型(如:Person
)的所有实例(如:person1
和person2
)能共享一些属性和方法。
需要注意的是,这里的name,age和sayName()都是原型对象上的属性和方法,并非实例本身所有。在调用构造函数(Person
)创建实例(person1
和person2
)后,实例内部将包含一个指针指向构造函数的原型对象(Person.prototype
)。 举个列子,读取person1.age
时person1
本身是没有age这个属性的, 但是程序会在读取属性时执行一次搜索,从实例本身开始,找到目标则停止,否则继续向上查找原型对象。所以person1.age
的值其实是在查找原型对象时返回的。
原型链和继承
说完原型,就来说继承。 继承的实现主要是通过原型链。 上面大概理了一下原型和实例的关系, person1
的指针是指向原型对象Person.prototype
的,Person.prototype
是在定义Person
时自动创建并有我们手动添加了一些属性和方法。试想一下,如果Person.prototype指向的是另一个类型的实例会怎样。
function superPerson() {
this.superProperty = 'super';
}
SuperPerson.prototype.superName = 'protoSuper';
SuperPerson.prototype.getSuperName = function() {
return this.superName;
}
function Person() {
this.personProperty = 'person';
}
Person.prototype = new SuperPerson(); // {superProperty: 'super'}
var person1 = new Person(); // {personProperty: 'person'}
person1.getSuperName(); // 'protoSuper'
alert(person1.superProperty); // 'super'
alert(person1.personProperty); // 'person'
如上,定义了一个SuperPerson
类型。在定义Person后我们首先创建一个SuperPerson
实例并将其赋值给Person.prototype
。上面讲原型时提到过,在调用构造函数创建实例后,实例内部将包含一个指针指向构造函数的原型对象,所以这里 new SuperPerson()
得到的实例对象内部也包含一个指针指向SuperPerson
的原型对象(即SuperPerson.prototype
),当然也会继承SuperPerson.prototype
上包含的属性和方法。
在读取 person1.getSuperName
方法时执行了3次搜索,第1次person1
本身,没有找到目标; 第2次便根据person1
内部指针指向的原型对象(Person.prototype)去查找,也没有找到;第3次根据Person.prototype
内部指针指向的原型(SuperPerson.prototype
)查找,找到目标。
在读取 person1.superProperty
时执行了两次查找,第1次仍然是没有找到,第2次查找Person.prototype
时,由于Person.prototype
是SuperPerson
的一个实例,所以Person.prototype
是具有superProperty
属性的。所以成功在Person
的原型对象上找到。
同样的person1
是Person
的实例,所以person1
本身是具有personProperty
这个属性的。所以读取person1.personProperty
时只执行了一次搜索。
如上面这种一个原型又是另一个类型的实例,这样层层递进,就构成了实力与原型的链条,就是作为的原型链。仿造着这种方法,我们还可以根据需要给这条原型链的头尾继续增加其他类型,来实现属性和方法的继承。
这里只是简单的说了说原型和继承的概念,其中当然还涉及了更为复杂的问题,还是留着下一次再细说吧。