关于JAVASCRIPT中 typeof 和 instanceof

关于上次我总结了typeof 和 instanceof 的区别,今天在前端早读课读到对于typeof和instanceof的原理解析,故在深入学习一下。

typeof和instanceof的主要区别是typeof用于判断number, string, object, boolean, function, undefined,symbol7种基本数据类型,而instanceof用于检测Object对象的引用类型,是对typeof的补充。

typeof和instanceof的原理解析的文章中对于typeof的本质摘抄如下:

1528286996138

null的低1-3位也是000,所以type of null也是object

而instanceof的原理可以看如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
function new_instance_of(leftVaule, rightVaule) { 
let rightProto = rightVaule.prototype; // 取右表达式的 prototype 值
leftVaule = leftVaule.__proto__; // 取左表达式的__proto__值
while (true) {
if (leftVaule === null) {
return false;
}
if (leftVaule === rightProto) {
return true;
}
leftVaule = leftVaule.__proto__
}
}

rightVaule与rightProto的原型链中的所有对象进行比较,如果相等就返回true。

也可以使用如下方法可以判断所有类型

1
2
3
4
5
6
7
8
9
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call('hi') // "[object String]"
Object.prototype.toString.call({a:'hi'}) // "[object Object]"
Object.prototype.toString.call([1,'a']) // "[object Array]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(() => {}) // "[object Function]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(Symbol(1)) // "[object Symbol]"

2018年5月8号

今天看了一道JS的基础面试题:

问题:如何准确判断一个变量是数组类型
答案:

1
2
3
4
var arr1 = [];  
console.log(arr1 instanceof Array); //打印结果:true。
console.log(typeof arr1); //打印结果:object.
提示:typeof 方法无法判断是否为数组

从中引出了typeof 和 instanceof 的区别和联系
查看了MDN的官方手册对于两者的用法如下:

  1. typeof操作符返回一个字符串,表示未经计算的操作数的类型。

用法:

1
2
3
typeof operand
or
typeof (operand)

typeof有如下返回值:

类型 结果
Undefined “undefined”
Null “object”(见下文)
Boolean “boolean”
Number “number”
String “string”
Symbol (ECMAScript 6 新增) “symbol”
宿主对象(由JS环境提供) Implementation-dependent
函数对象([[Call]] 在ECMA-262条款中实现了) “function”
任何其他对象 “object”

从上图可以反映出:typeof operand返回的结果为基本类型,对于引用类型其都返回object,所以var a = [];console.log(a);返回object。

注: 使用typeof操作符的时候,如果检测对象是函数,那么操作符返回"function" ,如果检测对象是正则表达式的时候,在Safari和Chrome中使用typeof的时候会错误的返回"function"。

  1. instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。

    用法:

1
2
3
4
5
6
object instanceof constructor

//object
//要检测的对象.
//constructor
//某个构造函数

如下是官方例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 定义构造函数
function C(){}
function D(){}

var o = new C();


o instanceof C; // true,因为 Object.getPrototypeOf(o) === C.prototype


o instanceof D; // false,因为 D.prototype不在o的原型链上

o instanceof Object; // true,因为Object.prototype.isPrototypeOf(o)返回true
C.prototype instanceof Object // true,同上

C.prototype = {};
var o2 = new C();

o2 instanceof C; // true

o instanceof C; // false,C.prototype指向了一个空对象,这个空对象不在o的原型链上.

D.prototype = new C(); // 继承
var o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true

注:如果表达式 obj instanceof Foo 返回true,则并不意味着该表达式会永远返回true,因为Foo.prototype属性的值有可能会改变,改变之后的值很有可能不存在于obj的原型链上,这时原表达式的值就会成为false。另外一种情况下,原表达式的值也会改变,就是改变对象obj的原型链的情况,虽然在目前的ES规范中,我们只能读取对象的原型而不能改变它,但借助于非标准的proto魔法属性,是可以实现的。比如执行obj.proto = {}之后,obj instanceof Foo就会返回false了。
所以对于typeof和instanceof的用法——typeof一般是检测的是基本数据类型,instanceof主要检测的是引用类型!