在了解函数原型之前,先由构造函数来进行引入:
//定义构造函数Plant
function Plant(name) {
this.name = name;
}
//实例化函数
let flower = new Plant('rose');
在尝试打印 flower
这个函数之后,会发现其存在一个浅色的属性:
1.__proto__
(隐式原型)
该属性为 flower
函数的内部属性。其指向的是一个对象,而这个对象也就是他的原型:构造函数 Plant
。然而
console.log(flower.__proto__ === Plant);//false
因为其指向的是 Plant
这个构造函数的原型。
2.prototype
(显式原型)
注:此属性为函数特有
而我们要找到 Plant
这个构造函数的原型,就需要用到 prototype
这个属性。prototype
属性所代表的即是构造函数 Plant
的原型对象。当利用构造函数实例化对象时,prototype
属性的值将会赋予给实例化对象的 __proto__
属性。故:
console.log(flower.__proto__ === Plant.prototype);//true
当我们再实例化一个函数对象:
let tree = new Plant('bigTree');
console.log(tree.__proto__ === Plant.prototype);//true
由此佐证:Plant
函数对象为两个实例化函数对象的“原型”。
3.原型链
我们再追根述源,Plant
这一构造函数,也是归于Object
这一数据类型,那么Object
的prototype
属性,是否赋予给了Plant
的__proto__
属性呢?
console.log(Object.prototype === Plant.__proto__);//false
console.log(Object.prototype === Plant.prototype.__proto__);//true
由上可知,Object
的prototype
属性值是赋予给了Plant
这个函数对象原型的,Plant
所存储的内部指针,便是指向Object
这一原型对象。
而要是再往上:
console.log(Object.prototype.__proto__ ) // null
prototype
(显式原型)均包含一个指向构造函数的指针,而__proto__
(隐式原型)均包含一个指向原型对象的内部指针
不难发现,由各项实例到Object
对象原型,其间都在传递着指向相应原型对象的指针,而正是这个__proto__
属性构成了原型链的基础结构
结语:
此文为初步认识函数原型与原型链,可能存在诸多不足,特此记录,以供来日翻阅。