知道js方法的实现原理,我们就能更好的使用它,知道为什么有这样的结果
关于typeof、instanceof的用法,如果不熟练,可以前往这里回顾
typeof 实现原理
js 在底层是怎么存储数据的类型信息呢?或者说,一个 js 的变量,在它的底层实现中,它的类型信息是怎么实现的呢?
其实,js 在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息👉
- 000:对象
- 010:浮点数
- 100:字符串
- 110:布尔
- 1:整数
but, 对于 undefined 和 null 来说,这两个值的信息存储是有点特殊的。
null:所有机器码均为0
undefined:用 −2^30 整数来表示
所以,typeof 在判断 null 的时候就出现问题了,由于 null 的所有机器码均为0,因此直接被当做了对象来看待。
然而用 instanceof 来判断的话👉
1 | null instanceof null |
null 直接被判断为不是 object,这也是 JavaScript 的历史遗留bug
typeof 的安全防范机制
首先,我们得知道undefined和undeclared的区别,未定义和未申明
1 | var a; |
根据这个特性,我们举个例子:
在程序中,我们使用DEBUG作为“调试模式”的开关,在输出调试信息到控制台之前,我们会检查DEBUG变量是否已经声明。顶层的全局变量声明 var DEBUG = true 只在debug.js文件中才有,而该文件只有在开发和测试的时候才会被加载到浏览器中,在生产环境不给予加载。我们应该怎么在全局环境中检查DEBUG而不会出现ReferenceError错误,这时候就需要用到typeof
1 | if(DEBUG) { // 这样会抛出异常 |
这不仅对用户定义的变量有用,还对内建的API有用
1 | if(typeof atob === 'undefined') { |
instanceof 操作符的实现原理
instanceof 主要的作用就是判断一个实例是否属于某种类型
1 | let person = function () { |
当然,instanceof 也可以判断一个实例是否是其父类型或者祖先类型的实例。
1 | let person = function () { |
根据它的用法,我们可以自己实现一个instanceof方法
1 | function new_instance_of (leftValue, rightValue) { |
其实 instanceof 主要的实现原理就是只要右边变量的 prototype 在左边变量的原型链上即可。因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果查找失败,则会返回 false,告诉我们左边变量并非是右边变量的实例。