JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的所拥有。
这也就意味着,我们可以把所有对象实例需要共享的属性和方法直接定义在 prototype 对象上。
function Person (name, age) {
this.name = name;
this.age = age;
}
console.log(Person.prototype);
Person.prototype.type = 'human';
Person.prototype.sayName = function () {
console.log(this.name);
}
var p1 = new Person(...);
var p2 = new Person(...);
console.log(p1.sayName === p2.sayName); // => true
这时所有实例的 type 属性和 sayName() 方法,其实都是同一个内存地址,指向 prototype 对象,因此就提高了运行效率。
构造函数、实例、原型三者之间的关系
任何函数都具有一个 prototype 属性,该属性是一个对象。
function F () {}
console.log(F.prototype) // => object
构造函数的 prototype 对象默认都有一个 constructor 属性,指向 prototype 对象所在函数。
console.log(F.prototype.constructor === F) // => true
通过构造函数得到的实例对象内部会包含一个指向构造函数的 prototype 对象的指针 __proto__。
var instance = new F()
console.log(instance.__proto__ === F.prototype) // => true
ps:__proto__ 是非标准属性。
实例对象可以直接访问原型对象成员。
instance.sayHi() // => hi!
总结:
-
任何函数都具有一个
prototype属性,该属性是一个对象 -
构造函数的
prototype对象默认都有一个constructor属性,指向prototype对象所在函数 -
通过构造函数得到的实例对象内部会包含一个指向构造函数的
prototype对象的指针__proto__ -
所有实例都直接或间接继承了原型对象的成员