前言
原型(Prototype)这一概念并非JS语言独有,但JS对其的应用和实现方式确实具有独特性,并在语言的核心机制中扮演着重要角色,也能解释一句话,即JS所有类型皆对象。废话不多说,直接进入主题:原型。
原型
原型
原型(prototype)是函数自带的一个属性,这个属性是一个对象,被称为原型对象,它定义了构造函数创建的实例对象的公共祖先.当我们使用构造函数(如new关键字)创建一个新对象时,这个新对象会自动链接到构造函数的原型对象上,原理为,新对象上的属性:proto(隐式原型) 会指向构造函数上的prototype(显示原型),使得这个实例对象可以使用构造函数上原型对象内的一些属性和方法,下面给出一份例子:
<script>
Person.prototype.say = function () {
console.log('hello');
}
Person.prototype.age = 18
function Person() {
this.name = 'ace'
}
let p = new Person();
let p1 = new Person();
p.name = 'ace1'
</script>
这时,我们通过浏览器的js引擎即可看出:
通过构造函数Person,创建的两个实例对象p以及p1除了通过this加入的属性name,还有一个属性[[Prototype]],这就是p上的隐式原型,这个写法是2015年更新的js版本Es6上新加的,其实就相当于__proto__,而它就指向了Person上的prototype,也就让它拥有了在Person.prototype挂载的属性age和say(),另一个属性constructor就很重要了,记录了是谁创建这个新对象的,还有一个[[Prototype]]则是因为这个原型对象本身也是一个对象,因此它同样可以拥有自己的[[Prototype]]属性,指向它的原型对象Object构造函数,展开这个[[Prototype]],我们就可以看见Object上挂载的一些方法
此时这个属性下对于我们比较重要的就是__proto__这个属性,事实上这个属性就是Person()了,展开后发现constructor则是指向了本身,之后的[[prototype]]属性则与上面的[[prototype]]一样,也是指向的Object()这个构造函数,最后的__proto__就是指向的Object()函数的Prototype了,展示了这个构造函数的原型上挂载了那些函数了,而它的__proto__则是null,就找到头了,事实上,这个链状关系就成为原型链,而这也解释了几乎所有类型都可称为对象,即都可以在源头找到Object。
原型链
v8引擎在查找对象中的属性时,如果没找到,就会顺着对象的隐式原型往上查找,还找不到,再顺着隐式原型的隐式原型往上找,直到找到null为止,在这过程中但凡有一个步骤能找到,就返回值。这个链状的查找过程就称为原型链。
特例
几乎所有对象都有原型,只有一个没有,即:
Object.create(null)
这样创建出的对象就没有原型
这里的create()方法,是挂载在Object原型上的方法,用于创建对象,括号内可以传入参数,传参后创建的新对象会以参数作为原型构建,在此时传入null,那么新对象就会以null为原型创建对象,而null是无意义的,也没有原型,更别说属性了,那么结果就如图片上的一样,是一个对象但它没有原型。
结语
原型是JS的又一座"大山",希望我的分享对你有帮助,我们下次再见!!!