与大部分面向对象语言不同,JavaScript中并没有引入类(class)的概念,但JavaScript仍然大量地使用了对象,为了保证对象之间的联系,JavaScript引入了原型与原型链的概念。
原型
下面是在JavaScript中创建一个对象的写法:
var obj = new FunctionName()
我们可以看出,JavaScript并非通过类而是直接通过构造函数来创建对象。
JavaScript中所有对象都有 toString
和valueOf
属性,给每个对象一个toString
和 valueOf
显然会造成极大的浪费。为此,JS的做法是将toString和valueOf放在一个对象里,然后让每一个对象的__proto__
来存储这个公共属性的地址。这个公共属性就是原型(proto)
- 每一个构造函数都拥有一个
prototype
属性,这个属性指向一个对象,也就是原型对象。当使用这个构造函数创建实例的时候,prototype属性指向的原型对象就成为实例的原型对象。- 原型对象默认拥有一个
constructor
属性,指向指向它的那个构造函数(也就是说构造函数和原型对象是互相指向的关系)。- 每个对象都拥有一个隐藏的属性
[[prototype]]
,指向它的原型对象,这个属性可以通过Object.getPrototypeOf(obj)
或obj.__proto__
来访问。- 实际上,构造函数的
prototype
属性与它创建的对象的[[prototype]]
属性指向的是同一个对象,即
对象.__proto__ === 函数.prototype
。
原型链
按上文所说,JavaScript中所有的对象都有原型对象。而原型对象自身也是一个对象,它也有自己的原型对象,这样层层上溯,就形成了一个类似链表的结构,这就是原型链(prototype chain)。
所有原型链的终点都是Object函数的prototype属性,因为在JavaScript中的对象都默认由Object()构造。Objec.prototype指向的原型对象同样拥有原型,不过它的原型是null,而null则没有原型。