谈谈你对原型的理解?
在 JavaScript 中,每个函数对象都有一个prototype 属性,这个属性指向函数的原型对象。使用原型对象的好处是所有对象实例共享它所包含的属性和方法。
什么是原型链?【原型链解决的是什么问题?】
原型链解决的主要是继承问题。
每个对象拥有一个原型对象,通过 __proto__
(读音: dunder proto) 指向其原型对象,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向null(Object.prototype.__proto__
指向的是null)。这种关系被称为原型链,通过原型链,一个对象可以拥有定义在其他对象中的属性和方法。
构造函数 Parent、Parent.prototype 和 实例 p 的关系如下:(p.__proto__ === Parent.prototype)
__proto__
(读音: dunder proto,dunder是“double underscore”的简拼)
prototype 和 __proto__
区别是什么?
prototype
是构造函数的属性。
__proto__
是每个实例都有的属性,指向其原型对象。
实例的__proto__
与其构造函数的prototype
指向的是同一个对象。
解析原型链
实例对象和构造函数都可以指向原型:
function Person() {
}
var person = new Person();
console.log(person.__proto__ === Person.prototype); //true
既然实例对象和构造函数都可以指向原型,那么原型是否有属性指向构造函数或者实例呢?
constructor
指向实例倒是没有,因为一个构造函数可以生成多个实例,但是原型指向构造函数倒是有的,这就要讲到第三个属性:construcotr,每个原型都有一个constructor属性指向关联的构造函数
function Person() {
}
console.log(Person === Person.prototype.constructor); //true
所以再更新下关系图:
综上我们已经得出:
function Person() {
}
var person = new Person();
console.log(person.__proto__ == Person.prototype) // true
console.log(Person.prototype.constructor == Person) // true
// 顺便学习一个ES5的方法,可以获得对象的原型
console.log(Object.getPrototypeOf(person) === Person.prototype) //true
原型对象也可能拥有原型,这样一层一层,最终指向null(Object.prototype.__proto__
指向的是null)。
最终关系图:
参考
- https://juejin.cn/post/6844903472836395022#heading-0
- https://juejin.cn/post/6844903815053852685#heading-17