JavaScript 中 原型与原型链
一直对 JS 中原型与原型链的内容不清楚,今天进行系统学习,做简单记录,方便以后加深印象;
构造函数
构造函数其实就是一个普通的函数, 但内部使用了 this
变量;
function Person(name, age) {
this.name = name;
this.age = age;
};
对构造函数使用 new
运算符,就能生成实例,并且 this
变量会绑定在实例对象上;
var person = new Person("赵云", 22);
console.log(person.age); // 22
这时 person
是 Person
构造函数的实例, person
会自动含有一个 constructor
属性指向它的构造函数 Person
;
console.log(person.constructor === Person); // true
由以上示例得出结论:实例的构造函数属性(constructor)指向构造函数;
原型对象
JavaScript 规定, 每个构造函数都有一个 prototype
属性, 指向一个对象; 这个对象的所有属性和方法, 都会被构造函数的实例继承;
什么是 prototype
属性:它是一个普通对象, 所有实例对象需要共享的属性和方法,都放在这个对象里面; 那些不需要共享的属性和方法,就放在构造函数里面;
Person.prototype.getAge = function() {
return this.age;
}
console.log(typeof Person.prototype); // object
console.log(Person.prototype);
那什么是原型对象呢?
其实 Person.prototype
就是原型对象, 将一些需要共享的属性和方法共享给实例对象的一个普通对象;
值得注意的是, 所有的原型对象都会获得一个constructor
属性, 这个属性指向 prototype
所在的函数(Person);
console.log(Person.prototype.constructor === Person); // true
想要彻底理解为什么会设计成这样,可以阅读文末的文章及其相关文章。
在构造函数的介绍里面,我们得到一个结论;似乎和这里有所联系
console.log(person.constructor === Person); // true
console.log(Person.prototype.constructor === Person); // true
因为 person 是 Person 的实例,person 才能有 constructor 属性;
因此得出一个结论:Person.prototype是构造函数Person的一个实例;
原型链
JS 在创建对象的时候,都有一个叫 __proto__
的内置属性,用于指向创建它的构造函数的原型对象;
console.log(person.__proto__ === Person.prototype); // true
person
实例有一个__proto__
属性,创建它的构造函数是 Person
, 构造函数的原型对象是Person.prototype
;
同样,Person.prototype
对象也有__proto__
属性,它指向创建它的函数对象(Object)的prototype
;
console.log(Person.prototype.__proto__ === Object.prototype); // true
Object.prototype
也有__proto__
属性,他比较特殊,为null
console.log(Object.prototype.__proto__); // null
我们把这个由__propto__
属性串起来的直到Object.prototype.__proto__
为null
的链叫做原型链;
总结
- 原型和原型链是JS实现继承的一种模型;
- 原型链的形成是真正是靠
__proto__
而不是prototype
;
ps: 先做简单记录,后期有新的理解再更新