简介
对象的 Symbol.hasInstance
属性,指向一个内部方法。当其他对象使用 instanceof
运算符,判断是否为该对象的实例时,会调用这个方法。比如,foo instanceof Foo
在语言内部,实际调用的是 Foo[Symbol.hasInstance](foo)
。详解见 阮一峰的ES6教程。
检验
基于上述内容我做了一个检验,在多个内置函数中均找到了 Symbol.hasInstance
方法,比如 Array
、String
、 Object
、Boolean
、Number
等。
Array[Symbol.hasInstance] // ƒ [Symbol.hasInstance]() { [native code] }
String[Symbol.hasInstance] // ƒ [Symbol.hasInstance]() { [native code] }
Object[Symbol.hasInstance] // ƒ [Symbol.hasInstance]() { [native code] }
Boolean[Symbol.hasInstance] // ƒ [Symbol.hasInstance]() { [native code] }
Number[Symbol.hasInstance] // ƒ [Symbol.hasInstance]() { [native code] }
并且这些方法都是同一个方法:
Array[Symbol.hasInstance] === String[Symbol.hasInstance] // true
String[Symbol.hasInstance] === Object[Symbol.hasInstance] // true
Object[Symbol.hasInstance] === Boolean[Symbol.hasInstance] // true
Boolean[Symbol.hasInstance] === Number[Symbol.hasInstance] // true
猜想: 这些方法可能都来自于原型链上,因为上述函数都是Function
的实例,于是找到上级的原型 Function.prototype
,果不其然。
Function.prototype.hasOwnProperty(Symbol.hasInstance) // true
用法
借用 阮一峰 老师写的例子:
class Even {
static [Symbol.hasInstance](obj) {
return Number(obj) % 2 === 0;
}
}
// 等同于
const Even = {
[Symbol.hasInstance](obj) {
return Number(obj) % 2 === 0;
}
};
1 instanceof Even // false
2 instanceof Even // true
12345 instanceof Even // false
是不是很酷,可以直接自定义
instanceof
的用法,于是我突发奇想,实现一个通过instanceof
判断是不是基本数据
类型的例子,如下:
class BasicType {
static [Symbol.hasInstance](data) {
// 把 除了null以外的所有基本数据类型放到一个数组里
const basics = ['string', 'number', 'boolean', 'undefined', 'symbol', 'bigint']
// 判断 typeof 之后的结果是否在这个数组中,或者 data 是否为 null
// 因为typeof null为'object',所以这里特殊判断一下
return basics.includes(typeof data) || data === null
}
}
基本数据类型验证
1 instanceof BasicType // true
'abc' instanceof BasicType // true
true instanceof BasicType // true
Symbol() instanceof BasicType // true
123n instanceof BasicType // true
undefined instanceof BasicType // true
null instanceof BasicType // true
引用数据类型验证
// 对象
({}) instanceof BasicType // false
// 数组
[] instanceof BasicType // false
// 函数
Array instanceof BasicType // false
// set
new Set() instanceof BasicType // false
// map
new Map() instanceof BasicType // false