什么是原型?
声明函数时 js会自动在你声明的函数对象(js一切皆对象)上挂载一些方法和属性 其中prototype属性就是 原型(也称为原型对象) 如下图:
这个原型对象里面保存着 constructor 自己的函数体(也就是Pro.prototype.constructor) 看下图就应该知道了吧 (Pro === Pro.prototype.constructor):
这个原型对象里面还保存着 __proto__ 这个__proto__指向的就是Object.prototype(Pro.prototype.__proto__ === Object.prototype 它们两个是一个“东西”) 里面保存着 所有,js自带对象 Object下的方法如下图:
在对象使用方法(或属性)时会查找自身原型(prototype)上的constructor有没有我使用的这个方法(或属性),如果没有就去自身原型(prototype)的就像指向父级原型的__proto__查找
这里我说一下 prototype是自身原型 __proto__是父级原型(指向父级原型 也就是父级原型)
找到父级原型 上图看到 父级原型上的constructor 下有很多方法。。。
我画绿线的地方 是我其他篇文章《对象属性类型》和《作用域和作用域链》介绍过的方法和属性。。有兴趣的可以去看一看
画绿圈的地方是我接下来要说的 构造函数下有__proto__和prototype(最上面的图显示出了这两个属性) 我前面还提到了 constructor就是自身函数体
用上图的Pro函数来举例子‘:
Pro函数 可称成为构造函数 也可称为函数体
Pro.prototype.constructor存储的是自身函数体
自身函数体.prototype === Pro.prototype
自身函数体就是Pro函数
所以这地方是一个无线循环
Pro.prototype.constructor === 自身函数体 (上面说了 自身函数体就是Pro函数 所以)Pro.prototype.constructor.prototype = = = Pro.prototype
有点乱 但是我相信多想想能理解。。。
上图还圈了一个属性 __proto__ 构造函数下有__proto__和prototype 这里我在解释一边 我上图圈的那个__proto__就是 构造函数Pro(函数体),
Function和Object一样都是js自带函数对象
所以说是Pro.__proto__.上面只说了原型上的__proto__下面说说 构造函数的__proto__ 指向 所有构造函数的__proto__都指向Function.prototype,
记住所有构造函数 包括他自己 Function函数
直接输出是看不到里面的东西的 但是也说明 有Function对象 然后我就想那new 出来一个实例 然后在 实例.__proto__ 但是我发现new出来的实例居然有 prototype (这里说明一下 除了Function的实例,其他对象的实例是没有prototype的)
这里 new Function 怎么会有prototype那 因为
new Function 也是创建函数的一种方式 (js规定的) 这时候就可以解释为什么 Function.__proto__ === Function.prototype
那么我们从Function上面得到什么了 毕竟所有构造函数的__proto__都指向 Function.prototype了
由于Function.prototype是无法直接访问的 所以我们使用Object.getOwnPropertyNames方法获取 Funciton.prototype上都有什么
上面也看到了。。。 Funciton.prototype有这些方法 证实一下 也证实上面说的,所有构造函数的__proto__都是Function.prototype
发现多一个 Symbol 这个是es6新增基础类型 需要使用Object.getOwnPropertySymbols获取
这个提一下 原型链顶端就是 Object.prototype.__proto__ = null 谷歌上控制台输出的不明确 这里用IE 输出一下
上图也是输出 Object.prototype.constructor.__proto__
所有构造函数的__proto__都是Function.prototype
那我为什么不知 直接 Object.__proto__
这就还是是想证明一下 Object.__proto__===Object.prototype.constructor.__proto__
上图发现了 在谷歌上输出 原型和IE上显示输出的方法不一样 比如 get __proto__ 、set __proto__ 和IE 的 __proto__
应该是谷歌浏览器 对js内置对象的一种修改 具体是怎么修改的和修改什么了 我也不清楚了。。。如果有知道的 请在下方留言谢谢!!!!
说的零零散散 最后需要总结一下。。。
原型就是 prototype 原型链 就是我在的原型上找不到的东西 我回去我的父级找 __proto__ 就是父级的指针 如下图:
我创建了一个构造函数 Pro
我又把Pro实例化 并且 赋值给了p
p.toString() 实例对象p下是没有toString的
p.__proto__ ===Pro.prototype 下constructor里面没有 toString方法
然后就找Pro.prototype.__proto__ ===Object.prototype
Object.prototype.constructor下找到了toString方法
所以才执行并且输出了 有兴趣可以百度查查 Object下的toString()方法怎么实现的。。。。
我为什么能使用toString()那 是因为我从 Object对象上继承而来的 所以这里说一下 js 是根据原型链来实现继承的啦 在有不懂了 可以看下面这个图 这个图要记下来
这个图我也忘了 是从哪篇文章找到得了 我是因为看了那篇文章 才明白的原型链 。。。在这里我感谢一下那篇文章的作者 还有图借我用一下 哈哈。。。