instanceof
操作符用于检查一个对象是否属于某个特定的 class。同时,它还考虑了继承。
语法
obj instanceof Class
如果obj隶属于Class类(或Class的衍生类),则返回true
class Rabbit {}
let rabbit = new Rabbit();
// rabbit 是 Rabbit class 的对象吗?
alert( rabbit instanceof Rabbit ); // true
它还可以与构造函数一起使用:
// 这里是构造函数,而不是 class
function Rabbit() {}
alert( new Rabbit() instanceof Rabbit ); // true
与诸如 Array 之类的内建 class 一起使用:
let arr = [1, 2, 3];
alert( arr instanceof Array ); // true
alert( arr instanceof Object ); // true
Symbol.hasInstance
- 可以在
Symbol.hasInstance
中自定义逻辑
过程:
- 如果这儿有静态方法
Symbol.hasInstance
,那就直接调用这个方法:
class Animal {
static [Symbol.hasInstance](obj) {
if (obj.canEat) return true;
}
}
let obj = { canEat: true };
alert(obj instanceof Animal); // true:Animal[Symbol.hasInstance](obj) 被调用
- 如果没有静态方法
Symbol.hasInstance
,使用obj instanceOf Class
检查Class.prototype
是否等于obj
的原型链中的原型之一。
obj.__proto__ === Class.prototype?
obj.__proto__.__proto__ === Class.prototype?
obj.__proto__.__proto__.__proto__ === Class.prototype?
...
// 如果任意一个的答案为 true,则返回 true
// 否则,如果我们已经检查到了原型链的尾端,则返回 false
objA.isPrototypeOf(objB)
- 如果
objA
处在objB
的原型链中,则返回true
。 - 所以,可以将
obj instanceof Class
检查改为Class.prototype.isPrototypeOf(obj)
。
检查Class
的原型Class.prototype
是否处在obj
的原型链中
但是Class
的constructor
自身是不参与检查的,检查过程只与原型链以及Class.prototype
有关
function Rabbit() {}
let rabbit = new Rabbit();
// 修改了 prototype
Rabbit.prototype = {};
// ...再也不是 rabbit 了!
alert( rabbit instanceof Rabbit ); // false
Object.prototype.toString
- 一个普通对象被转化为字符串时为
[object object]
let obj = {};
alert(obj); // [object Object]
alert(obj.toString()); // 同上
- 对于
number
类型,结果是[object Number]
- 对于
boolean
类型,结果是[object Boolean]
- 对于
null
:[object Null]
- 对于
undefined
:[object Undefined]
- 对于数组:
[object Array]
// 方便起见,将 toString 方法复制到一个变量中
let objectToString = Object.prototype.toString;
// 它是什么类型的?
let arr = [];
alert( objectToString.call(arr) ); // [object Array]
alert( objectToString.call(123) ); // [object Number]
alert( objectToString.call(null) ); // [object Null]
alert( objectToString.call(alert) ); // [object Function]
Sysbol.toStringTag
使用特殊的对象属性 Symbol.toStringTag
自定义
对象的 toString
方法的行为。
let user = {
[Symbol.toStringTag]: "User"
};
alert( {}.toString.call(user) ); // [object User]
对于大多数特定于环境的对象,都有一个这样的属性。下面是一些特定于浏览器的示例:
// 特定于环境的对象和类的 toStringTag:
alert( window[Symbol.toStringTag]); // Window
alert( XMLHttpRequest.prototype[Symbol.toStringTag] ); // XMLHttpRequest
alert( {}.toString.call(window) ); // [object Window]
alert( {}.toString.call(new XMLHttpRequest()) ); // [object XMLHttpRequest]
所以,如果我们想要获取内建对象的类型
,并希望把该信息以字符串
的形式返回,而不只是检查类型的话,我们可以用 {}.toString.call
替代 instanceof
。