添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

有一点需要留意, arr 同时还隶属于 Object 类。因为从原型上来讲, Array 是继承自 Object 的。

通常, instanceof 在检查中会将原型链考虑在内。此外,我们还可以在静态方法 Symbol.hasInstance 中设置自定义逻辑。

obj instanceof Class 算法的执行过程大致如下:

如果这儿有静态方法 Symbol.hasInstance ,那就直接调用这个方法:

大多数 class 没有 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

在上面那个例子中, rabbit.__proto__ === Rabbit.prototype ,所以立即就给出了结果。

而在继承的例子中,匹配将在第二步进行:

这里还要提到一个方法 objA.isPrototypeOf(objB) ,如果 objA 处在 objB 的原型链中,则返回 true 。所以,可以将 obj instanceof Class 检查改为 Class.prototype.isPrototypeOf(obj)

这很有趣,但是 Class 的 constructor 自身是不参与检查的!检查过程只和原型链以及 Class.prototype 有关。

创建对象后,如果更改 prototype 属性,可能会导致有趣的结果。

就像这样:

这是通过 toString 方法实现的。但是这儿有一个隐藏的功能,该功能可以使 toString 实际上比这更强大。我们可以将其作为 typeof 的增强版或者 instanceof 的替代方法来使用。

听起来挺不可思议?那是自然,精彩马上揭晓。

按照 规范 所讲,内建的 toString 方法可以被从对象中提取出来,并在任何其他值的上下文中执行。其结果取决于该值。

  • 对于 number 类型,结果是 [object Number]
  • 对于 boolean 类型,结果是 [object Boolean]
  • 对于 null [object Null]
  • 对于 undefined [object Undefined]
  • 对于数组: [object Array]
  • ……等(可自定义)
  • 让我们演示一下:

    // 特定于环境的对象和类的 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]

    正如我们所看到的,输出结果恰好是 Symbol.toStringTag (如果存在),只不过被包裹进了 [object ...] 里。

    这样一来,我们手头上就有了个“磕了药似的 typeof”,不仅能检查原始数据类型,而且适用于内建对象,更可贵的是还支持自定义。

    所以,如果我们想要获取内建对象的类型,并希望把该信息以字符串的形式返回,而不只是检查类型的话,我们可以用 {}.toString.call 替代 instanceof

    总结

    让我们总结一下我们知道的类型检查方法:

    正如我们所看到的,从技术上讲, {}.toString 是一种“更高级的” typeof

    当我们使用类的层次结构(hierarchy),并想要对该类进行检查,同时还要考虑继承时,这种场景下 instanceof 操作符确实很出色。