typeof和instanceof底层原理
typeof的原理是在检查数据类型的时候会先检查数据的底层类型标签
基于值的底层类型标签(Tag)判断:
JavaScript 引擎会为每个值分配一个 “类型标签”(32 位整数的低位几位),typeof 通过读取这个标签来返回对应类型:
数字(Number):标签以 000 开头(整数)或特殊编码(浮点数);
字符串(String):标签以 010 开头;
布尔值(Boolean):标签以 100 开头;
对象(Object):标签以 000 开头(引用类型共用此标签);
函数(Function):特殊标签(因需要快速区分可执行对象);
null:标签为全零(0x00),但被误判为对象(历史 Bug);
undefined:使用一个特殊的 “无效指针” 表示。
其次:typeof 在检测出其为引用数据类型后,还会再检测这个引用数据类型是否有实现[[call]]方法。不是,则返回object ,是,则返回function。
[[Call]] 是什么
“执行与此对象关联的代码。通过函数调用表达式调用。内部方法的参数是一个 this 值和一个包含调用表达式传递给函数的参数的列表。实现此内部方法的对象是可调用的。”
这是翻译的原话,简单点说,一个对象如果支持了内部的 [[Call]] 方法,那么它就可以被调用,就变成了函数,所以叫做函数对象。
相应地,如果一个函数对象支持了内部的 [[Construct]] 方法,那么它就可以使用 new 或 super 来调用,这时我们就可以把这个函数对象称为:构造函数。
局限性:
1、无法区分对象的具体类型(如Date、日期、正则等)都会返回object。
2、对于null会返回object(历史Bug)
3、对于基本包装类型(new String('a'))是返回object而非string
instanceof原理 本质是检查 “原型链”
底层原理
基于原型链查找:
A instanceof B 的执行逻辑是:
检查 B 是否有 prototype 属性(若没有则报错,如 null instanceof 123);
沿着 A 的原型链(A.proto)向上查找,看是否能找到 B.prototype;
如果找到则返回 true,否则返回 false。
示例:
javascript
运行
const arr = [];
arr instanceof Array; // true(arr.proto === Array.prototype)
arr instanceof Object; // true(Array.prototype.proto === Object.prototype)
function Foo() {}
const foo = new Foo();
foo instanceof Foo; // true(foo.proto === Foo.prototype)
特殊处理:
构造函数的 prototype 被修改后,instanceof 结果会改变:
javascript
运行
function Foo() {}
Foo.prototype = {};
const foo = new Foo();
foo instanceof Foo; // true(仍能找到修改后的 prototype)
基本类型(非对象)使用 instanceof 会直接返回 false:
javascript
运行
"abc" instanceof String; // false("abc" 是字符串字面量,不是对象)
new String("abc") instanceof String; // true(包装对象)
局限性
只能用于对象,对基本类型(如 number、string)返回 false;
原型链被修改时,结果可能不符合预期;
跨 iframe 或 window 时,因原型链不共享,可能误判(如 iframeArr instanceof Array 为 false)。
三、核心区别对比
特性 typeof instanceof
判断依据 底层类型标签(Tag) 原型链查找(proto vs prototype)
适用类型 所有类型(侧重原始类型) 仅对象(判断实例关系)
返回值 字符串(如 "number"、"object") 布尔值(true/false)
典型用途 判断原始类型(number、string 等) 判断对象的具体类型(Array、Date 等)
局限性 无法区分具体对象类型 不能判断基本类型,受原型链影响
四、使用场景建议
判断原始类型:用 typeof(注意 null 需单独判断):
javascript
运行
typeof x === 'number';
typeof x === 'string';
x === null; // 单独判断 null
判断对象的具体类型:用 instanceof 或 Object.prototype.toString.call():
javascript
运行
arr instanceof Array;
date instanceof Date;
// 更可靠的跨环境判断
Object.prototype.toString.call(arr) === '[object Array]';
判断函数:两者均可,但 typeof 更简洁:
javascript
运行
typeof fn === 'function';
fn instanceof Function; // 也可行
浙公网安备 33010602011771号