(JavaScript)类检查:”instanceof“(Symbol.hasInstance、objA.isPrototypeOf(objB)、Sysbol.toStringTag)

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的原型链中
    但是Classconstructor自身是不参与检查的,检查过程只与原型链以及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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值