版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_26542493/article/details/102813507</a>
问题
初学js的同学,总是搞不清楚js中的原型是什么东西,看着控制台打印出来的一串串proto,迷惑不已。
例如我定义一个Person,创建一个实例p,并打印实例。
function Person(){}
var p = new Person();
console.log(p)
图中,打印出来一个Person的实例对象p,
这个对象有个proto 属性,这个是什么东西?
proto属性下又有constructor属性和proto属性。
constructor是什么,为什么打印结果是 Person()?
另外一个proto是什么?
为了解答上边的问题,我们需要了解一些相关概念。
一、原型
prototype
首先,说明一下,JS中,万物皆对象。
每个函数对象都有一个属性prototype(函数对象特有属性),这个属性是一个引用,指向一个对象,这个对象的作用就是包含所有实例共享的属性和方法。我们把这个对象就叫做原型对象,也叫显式原型。
proto
每个对象都有一个属性proto,也可称为隐式原型,对象的隐式原型指向创建该对象的构造函数的原型(prototype)。
constructor
函数的原型对象有一个constructor属性,这个属性是一个引用,用于指向原构造函数。
关系
我们怎么理解上边的概念,而它们之间又有什么联系呢?
我们不妨打印出来p.proto属性:
可以看到,打印出来是一个对象,对象里边有个属性constructor。
constructor是什么呢,打印如下:
可以看到,打印出来是函数,代表的就是Person构造函数本身.
再依次打印出来Person构造函数的原型Person.prototype,
和其原型的属性constructor:
从上图我们就可以得出:
1.实例对象p有属性proto 指向的就是创建它的构造函数的原型对象Person.prototype。
2.构造函数的原型对象Person.prototype的属性constructor指向Person构造函数本身。
我们可以验证一下:
但是,可能又有些同学有疑惑了,那既然所有对象都有proto属性,
那构造函数Person()的属性proto指向谁呢?
当然是指向它的构造函数的原型对象了。
函数的构造函数就是Function(),因此这里的proto指向Function.prototype。
那原型对象也是对象,它的proto属性指向谁呢?
同理,指向它的构造函数的原型对象,即Object.prototype。
这里,我们就不得不提一下,原型链的概念了。
原型链
原型链是一种机制,指的是js中,每个对象都有一个属性proto,指向它的构造函数的原型对象。原型对象也是一个对象,因此也有proto属性指向原型对象的原型对象,这样一层层向上直到对象的原型对象为空(Object的原型对象Object.prototpye的属性proto为null)。
因此,例子中原型链的关系如下:
p.proto 指向 Person.prototype,
Person.prototype.proto指向的就是Object.prototype,
Object.prototpye.proto 指向null
为了理解上边例子的原型链关系,我们画一张图来增加理解:
至此,上边的问题是不是心里已经有答案了呢。
总结
1.每个对象都有一个proto属性,指向创建它的构造函数的原型对象。
作用:构成原型链,用于实现基于原型的继承。
2.函数除了有proto属性,还有一个prototype属性,用来指向函数的原型对象。
作用:用于实现基于原型的继承和属性共享。
因此,你会在很多地方见到有类似这样的写法:
function Person(){}
Person.prototype.hello = function(){
console.log("hello")
}
上边代码表示,所有Person创建的实例对象都可以共享hello方法。
3.构造函数的原型对象有属性constructor,指向构造函数本身。
PS:欢迎关注公众号:「如若清风」,一起交流学习。