Fork me on GitHub

typeof与instanceof

typeof

对于原始类型,除了null都可以显示正确的类型
typrof null会输出object,这只是js存在的一个历史遗留bug

在js最初版本中用的是32位系统,为了性能考虑受使用低位存储变量的类型信息,000开头表示对象,然而null表示未全零,所以它被判断为object。现在内部类型判断代码已经改变了,但是这个bug依旧保留下来

1
2
3
4
5
typeof 123 // 'number'
typeof '123' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'

但是对于对象来说,除了函数都显示为object,因此typeof并不能准确判断变量类型

1
2
3
typeof [] // 'object'
typeof {} // 'object'
typeof console.log // 'function'

instanceof

想正确判断对象的正确类型,可以使用instanceof,因为内部机制是通过原型链来判断的

1
2
3
4
5
6
7
8
9
const Father = function() {};
const son = new Father();
son instanceof Father; // true

const str = 'test string';
str instanceof String; // false

const str1 = new String('test string1');
str1 instanceof String; // true

对于原始类型不能直接通过instanceof来判断类型,可以借助Symbol.hasInstance

Symbol.hasInstance 用于判断某对象是否为某构造器的实例。
例如,你可以这样来定义MyArray 的 instanceof 行为:

1
2
3
4
5
6
7
class MyArray {
static [Symbol.hasInstance](instance) {
return Array.isArray(instance);
}
}

console.log([] instanceof MyArray)

类似地,通过Symbol.hasInstance对原始类型做类型判断

1
2
3
4
5
6
class PrimitiveString {
static [Symbol.hasInstance](instance) {
return typeof instance === 'string'
}
}
console.log('123' instanceof PrimitiveString) // true

instanceof的实现原理

instanceof 可以正确的判断对象的类型,内部机制是通过判断对象的原型链中是不是能找到类型的 prototype。
因此,我们也可以试着实现一下instanceof

思路:
1.获取类型的原型
2.获取对象的原型
3.循环判断对象的原型是否等于类型的原型,直到对象原型为null,即原型链顶端null

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// left为对象,right为类型
function myInstanceof(left, right) {
let prototype = right.prototype,
left = left.__proto__
while(true) {
if (left == null) { // null || undefined
return false;
}
if (prototype === left) {
return true;
}
left = left.__proto__
}
}

本文标题:typeof与instanceof

文章作者:tongtong

发布时间:2019年03月16日 - 14:03

最后更新:2019年05月09日 - 13:05

原始链接:https://ilove-coding.github.io/2019/03/16/typeof与instanceof/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

坚持原创技术分享,您的支持将鼓励我继续创作!
-------------本文结束-------------