构造函数、原型对象和实例对象的关系
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__
-
所有实例都直接或间接继承了原型对象的成员