这是我参与8月更文挑战的第1天,活动详情查看: 8月更文挑战
前言
借着这次8月更文挑战,我想学习和巩固一下Js基础和vue源码,刚好以文章的形式输出。
我记得红宝书中的第一章有句话:JavaScript是一种专为于网页交互而设计的脚本语言。Js在前端的地位不言而喻,而掌握Js的基础更是重中之重。接下来的文章会一点一点的分知识点去学习Js。Js的知识图谱
概念
原型是定义了一些公用的属性和方法,利用原型创建出来的新对象实例会共享原型的所有属性和方法。每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性。
原型链是原型对象创建过程的历史记录,当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构。
初步探索
正文
首先构造一个函数Person,该函数的原型是其prototype,用该构造函数Person创建一个对象person1,可以看见该对象是从Person函数原型继承属性。person1这个对象的隐性原型__proto__也和原来函数原型相等。
总结:每个函数都有一个原型(prototype),然后每个对象都有一个隐性原型(proto),对象的隐性原型(proto)和其构造函数(constructor)的原型(prototype)相等。
也就有了这样一个公式:对象的隐性原型等于其构造函数的原型。
obj.__proto__ === obj.constructor.prototype
代码
function Person(){} //构造一个函数
Person.prototype // 函数原型
Person.prototype.name='wangxiaoer' //给原型新增一个name属性
const person1 = new Person() //利用函数创建新的对象person1
person1.__proto__ //隐性原型
一图概括(侵删)
进一步探索
正文
从上我们知道函数都有原型,对象都有隐性原型。你也肯定听过函数是第一类对象(first-class object),被称为一等公民。所以函数也是有构造函数和隐性原型,而Person的构造函数为Function,所以由第一步得出的公式可以得到Person.__proto__ === Person.constructor.prototype。Function函数比较特殊,我们等等新开个章节来说明。
那么上面的函数Person的原型会是什么呢,首先Person的原型的隐性原型和Object的原型相等,而Object的原型对象的隐性原型为null,Object.prototype.__proto__===null。
为什么原型链的终点是null,而不是Object.prototype?
代码
function Person(){} //定义一个函数
Person.__proto__ === Person.constructor.prototype //对象的隐性原型等于其构造函数的原型
Person.__proto__===Function.prototype // Person函数的构造函数是Function
Person.prototype.__proto__===Object.prototype//Person的原型的隐性原型和Object的原型相等
Person.prototype.__proto__.__proto__===null//Object的原型对象的隐性原型为null
一图概括(侵删)
探索一下Function
正文
刚刚说到函数Person的构造函数是Function,
Function是一个构造函数,用来生成函数的构造函数。那么,String(),Boolean(),Number()这些函数都是Function构造出来的,new出来的,也就是说String(),Boolean(),Number()这些函数(函数也是广义对象)是Function的实例对象。
//任意函数的隐性原型__proto__都===Function.prototype
Person.__proto===Function.prototype //true
// String、Number、Boolean、Object、Function...这些函数
小结论:所有函数实例.__proto__就是Function构造函数的原型(Function.Prototype),函数而函数实例也包括他自己。
而这样也导致了一个奇怪的现象:Function函数的原型和隐性原型是相等的。
Function的原型的隐性原型和Object的原型相等
代码
//任意函数的隐性原型__proto__都===Function.prototype
Person.__proto===Function.prototype //true
// String、Number、Boolean、Object、Function...这些函数
String.__proto===Function.prototype //true
Number.__proto===Function.prototype //true
Boolean.__proto===Function.prototype //true
Object.__proto===Function.prototype //true
Function.__proto===Function.prototype //true
Function.prototype===Function.__proto__//Function函数的原型和隐性原型是相等
Function.prototype.__proto__===Object.prototype//Function的原型的隐性原型和Object的原型相等
Function.prototype.__proto__.__proto__===null//
小结
- 如果把函数看成对象,那么
任意函数.__proto__ === Function.prototype - 如果把
Function看成对象,那么Function.__proto__ === Function.prototype - Function的原型的隐性原型和Object的原型相等,
Function.prototype.__proto__===Object.prototype
本文小结
- 对象的隐性原型等于其构造函数的原型。
- Object原型的隐性原型是null
- 任意函数的隐性原型__proto__都===Function.prototype
- 任意函数的隐性原型(Function的原型)的隐性原型和Object的原型相等
- 每层的
__proto__都指向上一层的原型,所以一层一层的__proto__组成的链就成为原型链
熟能生巧(Practice make perfect!)。 以上是对原型的一些基本解释和结论,各位大佬,如果看见错误的地方感谢帮忙指出,谢谢了!