typeof
主要是用来判断一个变量的类型
几个特殊的情况记一下:
1 2 3 4 5 6
| typeof null typeof {} typeof [] typeof Object typeof Function typeof undefined
|
看到上边 typeof Object
的结果是 function
这里其实因为 Object 是一个构造函数, 而不是一个真正的对象, 只有实例化之后才会给出 object
的结果
可以看一下下边代码:
1 2 3 4
| console.log(typeof Object);
let ahui = new Object(); console.log(typeof ahui);
|
再看到上边: typeof null
typeof {}
typeof []
结果都是 object, 很显然, 我们是不能通过 typeof 来判断一个对象的具体类型的,通常我们会通过 Object.prototype.toString
的方法来实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| Object.prototype.toString.call(1)
Object.prototype.toString.call('hi')
Object.prototype.toString.call({a:'hi'})
Object.prototype.toString.call([1,'a'])
Object.prototype.toString.call(true)
Object.prototype.toString.call(() => {})
Object.prototype.toString.call(null)
Object.prototype.toString.call(undefined)
Object.prototype.toString.call(Symbol(1))
|
到这里, 好像还没说到 typeof 的实现原理,其实很简单,通常情况下,我们只需要知道他的用法以及一些注意点就行:
JS 要底层存储变量的时候, 会在变量的机器码的低位 1 ~ 3 位存储其类型信息
instanceof表示指定对象是否为某个构造函数的实例。
比如下边代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const Person = function (name) { this.name = name; }
const ahui = new Person('ahui'); const angeli = { name: 'angele' }
console.log(ahui instanceof Person);
console.log(ahui.__proto__ === Person.prototype);
console.log(angeli instanceof Person);
|
当然,instanceof 也可以判断一个实例是否是其父类型或者祖先类型的实例
1 2 3 4 5 6 7 8
| const Person = function () {} const Programmer = function () {}
Programmer.prototype = new Person() const ahui = new Programmer();
console.log(ahui instanceof Programmer); console.log(ahui instanceof Person);
|
再看几个有意思的例子:
1 2 3 4 5 6 7 8 9 10 11 12
| function Foo() {}
console.log(Object instanceof Object) console.log(Function instanceof Function) console.log(Number instanceof Number); console.log(String instanceof String); console.log(Function instanceof Object) console.log(Object instanceof Function)
console.log(Foo instanceof Foo) console.log(Foo instanceof Object) console.log(Foo instanceof Function)
|
看到上边的 instanceof
有没有感觉很有意思,下边让我们来讲一下为什么会这样:
先看一张图片
如果看这个图片表示看不懂的, 可以先看一下这篇文章: js 中__proto__
和 prototype
的区别和关系
如果有同学对这张图表示怀疑的,就像我,可以先在控制台试一下下边的代码:
1 2 3 4
| Object.__proto__ === Function.prototype; Function.__proto__ === Function.prototype; Function.prototype.__proto__ === Object.prototype; console.log(Object.prototype.__proto__);
|
下边我们再来理解 Object instanceof Object
为 true
1 2 3 4 5 6 7 8 9 10 11 12
| ObjectL = Object, ObjectR = Object;
O = ObjectR.prototype = Object.prototype L = ObjectL.__proto__ = Function.prototype
O != L
L = Function.prototype.__proto__ = Object.prototype
O == L
|
同理, 我们可以通过上边那张 js 原型的关系图推算出 其它所有的 instanceof
自己手动实现 instanceof
现在, 我们知道 instanceof 的原理了, 那么,自己手动去实现一个 instanceof 是很简单的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| function instanceof_myself(L, R) { const O = R.prototype; L = L.__proto__;
while(true) { if (L === null) { return false; } if (L === O) { return true; } L = L.__proto__; } }
const Person = function () {} const ahui = new Person();
console.log(ahui instanceof Person) console.log(instanceof_myself(ahui, Person));
|
参考地址:
浅谈 instanceof 和 typeof 的实现原理
JavaScript instanceof 运算符深入剖析