我在写一篇图解prototype和__proto__的区别时,搜资料搜到了一个有意思的现象,下面这两个运算返回的结果是一样的:

Function instanceof Object;//true
Object instanceof Function;//true

这个是怎么一回事呢?要从运算符instanceof说起。

一、instanceof究竟是运算什么的?

我曾经简单理解instanceof只是检测一个对象是否是另个对象new出来的实例(例如var a = new Object(),a instanceof Object返回true),但实际instanceof的运算规则上比这个更复杂。

首先w3c上有官方解释(传送门,有兴趣的同学可以去看看),但是一如既往地让人无法一目了然地看懂……

知乎上有同学把这个解释翻译成人能读懂的语言(传送门),看起来似乎明白一些了:

//假设instanceof运算符左边是L,右边是R
L instanceof R
//instanceof运算时,通过判断L的原型链上是否存在R.prototype
L.__proto__.__proto__ ..... === R.prototype ?
//如果存在返回true 否则返回false

注意:instanceof运算时会递归查找L的原型链,即L.__proto__.__proto__.__proto__.__proto__...直到找到了或者找到顶层为止。

所以一句话理解instanceof的运算规则为:

instanceof检测左侧的__proto__原型链上,是否存在右侧的prototype原型。

二、图解构造器Function和Object的关系

我们再配合代码来看一下就明白了:

//①构造器Function的构造器是它自身
Function.constructor=== Function;//true //②构造器Object的构造器是Function(由此可知所有构造器的constructor都指向Function)
Object.constructor === Function;//true //③构造器Function的__proto__是一个特殊的匿名函数function() {}
console.log(Function.__proto__);//function() {} //④这个特殊的匿名函数的__proto__指向Object的prototype原型。
Function.__proto__.__proto__ === Object.prototype//true //⑤Object的__proto__指向Function的prototype,也就是上面③中所述的特殊匿名函数
Object.__proto__ === Function.prototype;//true
Function.prototype === Function.__proto__;//true

三、当构造器Object和Function遇到instanceof

我们回过头来看第一部分那个“奇怪的现象”,从上面那个图中我们可以看到:

Function.__proto__.__proto__ === Object.prototype;//true
Object.__proto__ === Function.prototype;//true

所以再看回第一点中我们说的instanceof的运算规则,Function instanceof Object 和 Object instanceof Function运算的结果当然都是true啦!

如果看完以上,你还觉得上面的关系看晕了的话,只需要记住下面两个最重要的关系,其他关系就可以推导出来了:

1、所有的构造器的constructor都指向Function

2、Function的prototype指向一个特殊匿名函数,而这个特殊匿名函数的__proto__指向Object.prototype

至于prototype和__proto__的关系如何推导,可以参考我写的上一篇博客《三张图搞懂JavaScript的原型对象与原型链

最新文章

  1. INI配置文件分析小例子
  2. java5 ReadWriteLock用法--读写锁实现
  3. iOS 学习笔记 九 (2015.04.02)IOS8中使用UIAlertController创建警告窗口
  4. 12232 - Exclusive-OR
  5. Wii硬盘游戏管理
  6. C读txt到二维数组
  7. cordova安装--创建ionic项目
  8. JMS理解2
  9. Number()和new Number()的区别以及一种简单实现
  10. Python【第四课】 模块 and 包
  11. Highcharts之折线图
  12. [Spring] Annotation注释
  13. mac mysql 操作
  14. webhttpbinding、basichttpbinding和wshttpbinding的区别
  15. MT【182】系数奇怪的二次函数
  16. python第十四课--排序及自定义函数之自定义函数(案例二)
  17. rxjava rxandroid使用遇到的坑
  18. vue 改变我们插值的符号{{}}改为${}
  19. hdu-5748 Bellovin(LIS)
  20. JavaScript对列表节点的操作:删除指定节点、删除最后一个节点、删除第一个节点、删除所有节点、增加节点

热门文章

  1. R实战:grid包
  2. STM8S——Flash program memory and data EEPROM
  3. 图片转换成word 公式
  4. UNITY_资源路径与加载外部文件
  5. 学习python,第五篇
  6. BOM 头是什么,怎么除去
  7. nodejs 几篇有用的文章
  8. FFmpeg简单转码程序--视频剪辑
  9. Linux基础入门--04
  10. 20172319 2018.04.11-16 《Java程序设计教程》 第6周学习总结