判断数据类型 typeof 和 instanceof
Jioho 6/28/2020 Javascript
判断方式:
# 1. typeof
typeof
对于基本类型,除了null
都可以显示正确的类型typeof
对于对象,除了函数都会显示object
- 主要用于判断数据是不是基本数据类型:
String
、Number
、Object
、Null
、Undefined
,但是无法判断出 function(有些浏览器会出错)、array、regExp
console.log(typeof '') // string
console.log(typeof []) // object
console.log(typeof {}) // object
console.log(typeof 1) // number
console.log(typeof null) // object
console.log(typeof undefined) // undefined
console.log(typeof true) // boolean
console.log(typeof function() {}) // function
console.log(typeof /\d/) // object
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 2. instanceof
- 主要的目的是用来检测
引用类型
,判断Array
和RegExp
,无法准确判断 Function A对象 instanceof B对象
: 判断 A 对象原型链上 是否有 B 对象原型 !!!instanceof
可以正确的判断对象的类型,因为内部机制是通过判断对象的原型链中是不是能找到类型的prototype
console.log([] instanceof Array) //true
console.log({} instanceof Object) //true
console.log(/\d/ instanceof RegExp) //true
console.log(function() {} instanceof Object) //true
console.log(function() {} instanceof Function) //true
console.log('' instanceof String) //false
console.log(1 instanceof Number) //false
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 3. Object.prototype.toString
这是对象的一个原生原型扩展函数,用来精确的区分数据类型
var type = Object.prototype.toString
console.log(type.call('')) // [object String]
console.log(type.call([])) // [object Array]
console.log(type.call({})) // [object Object]
console.log(type.call(false)) // [object Boolean]
console.log(type.call(null)) // [object Null]
console.log(type.call(undefined)) // [object Undefined]
console.log(type.call(function() {})) // [object Function]
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# instanceof 详解
上面只是简单的介绍了下 instanceof。接下来深入了解一下这个运算符
看个简单的 demo。如果对上面的内容已经熟悉,并且原型和原型链,原型继承也有一定了解的,看下面这段代码一定一点都不吃力
// 判断 foo 是否是 Foo 类的实例 , 并且是否是其父类型的实例
function Aoo() {}
function Foo() {}
Foo.prototype = new Aoo() //JavaScript 原型继承
var foo = new Foo()
console.log(foo instanceof Foo) //true
console.log(foo instanceof Aoo) //true
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
来一个复杂的
function Foo() {}
console.log(Object instanceof Object) // 01
console.log(Function instanceof Function) // 02
console.log(Number instanceof Number) // 03
console.log(String instanceof String) // 04
console.log(Function instanceof Object) // 05
console.log(Foo instanceof Function) // 06
console.log(Foo instanceof Foo) // 07
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
查看答案
编号 | 01 | 02 | 03 | 04 | 05 | 06 | 07 |
---|---|---|---|---|---|---|---|
答案 | true | true | false | false | true | true | false |
- 为什么 Object 和 Function instanceof 自己等于 true,而其他类 instanceof 自己却又不等于 true 呢?
要想知道这个答案,自己写一个 instanceof 了解下原理
# 自己实现一个 instanceof
- 我们都知道,instanceof 是根据原型链,判断当前对象的原型链是否存在需要判断的对象
- 原型链是一直找下去的,所以我们得有一个不断循环根据原型链找上级原型的的方法
(while(true)就很合适)
- 总不可能一直找下去,原型链顶端就是
null
,如果找到顶端都还没找到,那就是结束了
于是写出这样的代码:
/**
* L 表左表达式 即L为变量
* R 表示右表达式 R为类型
*/
function my_instance_of(L, R) {
let RP = R.prototype // 取右表达式的 prototype 值
L = L.__proto__ // 取左表达式的__proto__值
while (true) {
if (L === null) {
return false
}
if (L === RP) {
return true
}
L = L.__proto__
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 解释下 为什么 Object 和 Function instanceof 等于自己
根据上面推导出来的 my_instance_of
方法,我们把 Object
套进去看一看效果
my_instance_of(Object, Object) // true
1
步骤分析
- 传入了 2 个
Object
。也就是说L
和R
都是Object
- RP = Object.prototype
- L =
Object.__proto__
- 第一轮对比
Object.__proto__ !== Object.prototype
2 个不相等 - L 重新赋值为
Object.__proto__.__proto__
重点来了Object.__proto__
和Function.prototype
是相等的!。所以这时候的L === Object.__proto__.__proto__ === Function.prototype.__proto__
- 重新进入 while,根据 5 的推导,
Function.prototype.__proto__ === Object.prototype
为 true! - 返回,Object instanceOf Object 比较结果为 true
我怀疑你在凭空想象:为什么 Object.__proto__
和 Function.prototype
是相等的??
先看基础: 内置对象(函数对象)和普通对象区别
内置对象概念:js 已经创建好了,你不用自己再创建的对象(免去 new 的步骤),直接就可以调用
发现 Object
是函数对象。函数对象的原型链指向函数(Function)的原型,有问题吗?没有问题!
所以 instanceOf 的对比是没错的。Function instaceOf Function
同理:
- RP = Function.prototype
- L =
Function.__proto__
- L === RP 成立。因为
Function
也是函数对象,函数对象的原型链指向 Function 的原型
# 得出一个小结论
内置对象(函数对象)
用 instaceOf Function 肯定会返回 ture- instaceOf 会不断根据原型链往上查找,最终找到 null 停止