在了解原型&原型链之前,一些前置知识要知道
- 普通函数、构造函数、和实例对象之间的关系。
- 函数的本质就是对象。
一、构造函数、普通函数和实例对象之间的关系,看代码:
//它只是一个普通的函数
const Animal = function(){
}
//Animal此时是构造函数
//dog是实例对象
const dog = new Animal();
这个例子说明了,Animal是普通函数
。
new Animal()是构造函数
。
new 出了个对象dog是实例对象
。
进入正题:
prototype
、__proto__
、 constructor
,这几个属性是什么,他们之间的关系。
这是一张原型关系图,我们一步一步把问题拆分去理解。
1.prototype
首先介绍的是prototype,它是函数独有的
,我们可以在相关项目源码中经常看到他的身影,示例:
function Person() {
}
// prototype是函数才会有的属性
Animal.prototype.name = 'kiki';
var dog = new Animal();
console.log(dog.name) //kiki
所以我们可以从关系图中发现函数的prototype属性指向了一个对象,
这个对象就是实例原型
。
原型是什么:在JavaScript中原型是一个prototype对象,它从其他对象继承功能特性,用于表示类型之间的关系。
2.__ proto __
每一个对象(null除外),都有一个__proto__属性
,这个属性会指向该对象的原型也就是实例原型
。
function Aminal() {
}
var dog = new Aminal();
// 证明 dog实例与构造函数都指向原型
console.log(dog.__proto__ === Aminal.prototype); // true
3.constructor
实例对象和构造函数都可以指向原型,那么原型可不可以指回去呢?
指回实例的没有,因为构造函数可以生成很多实例。
function Aminal() {
}
// 实例有很多
var dog = new Aminal();
var cat = new Aminal();
var duck = new Aminal();
指回构造函数的有,就是constructor属性,每一个原型都有一个constructor指回构造函数。
function Aminal() {
}
var dog = new Aminal();m
// 证明 dog实例与构造函数都指向原型
console.log(dog.__proto__ === Aminal.prototype); //
true
// 证明原型可以指回构造函数
console.log(Aminal === Aminal.prototype.constructor); // true
// 注意:不是说实例没有constructor吗?
// 是的,但结果为true,是因为dog.__prop__指向的是原型,实际还是实例原型通过constructor指回构造函数
console.log(Aminal === dog.constructor); // true
原型的指向
我们已经讲了原型也是一个对象,既然是对象,就会存在__proto__属性。
Obejct()就是我们常见的初始化new出的对象。
var obj = new Object();
原型链
我们知道实例原型是一个对象,实例原型的原型的原型...最终的指向是什么?
是null;而我们熟知的instanceof用法就是沿着原型链找,如果属性不在原型链上,则会一直找,直到为null。
console.log(Object.prototype.__proto__ === null) // true
白色指向就是其原型链。
更新下图: