a instanceof b returns false 即使 b 在 a 的原型链中

a instanceof b returns false even though b is in a's prototype chain

还有一个 instanceof 问题。 我正在使用来自 antlr4 解析器的一些自动生成的代码。解析器工作正常,我将它与 ace 一起插入,语法突出显示工作,......到目前为止一切顺利。但是现在发生了一件非常奇怪的事情。我写了自己的 parserTreeListener,由于 instanceof 调用 return 错误结果而失败。

将问题分解为一个小程序是可行的。但是就像魔术一样,即使它使用相同的代码(解析器、词法分析器、监听器...),一切都很顺利

不够奇怪,在 chrome devtools 中调试问题,向我展示了对象 t 原型链 (__proto__) 确实是 TerminalNode 的一个实例但是尽管如此,调用 t instanceof TerminalNode returns false

不幸的是,我无法发布主项目的代码,它失败了(至少现在还没有)。也许有人知道为什么以及何时会出现此类问题。

一些可能的解释(尽管我怀疑)

antlr4 中的这段代码失败了:

ParseTreeWalker.prototype.walk = function(listener, t) {
var errorNode = t instanceof ErrorNode ||
        (t.isErrorNode !== undefined && t.isErrorNode());
if (errorNode) {
    listener.visitErrorNode(t);
} else if (t instanceof TerminalNode) { /*here t fails on first TerminalNode*/
    listener.visitTerminal(t);
} else {
    this.enterRule(listener, t);
    for (var i = 0; i < t.getChildCount(); i++) {
        var child = t.getChild(i);
        this.walk(listener, child);
    }
    this.exitRule(listener, t);
}
};

一些调试信息

两个脚本 return 在我键入时的断点处相同:

$ var obj = t; while(obj) console.log(obj = Object.getPrototypeOf(obj));
TerminalNode {}
ParseTree {}
SyntaxTree {}
Tree {}
Object {}
Object {}

a instanceof b 检查 a 是否继承自 b.prototype,而不是 b.

如果要测试b本身是否出现在a的原型链中,可以使用

b.isPrototypeOf(a);

一些示例:

[] instanceof Array;                           // true
Array.isPrototypeOf([]);                       // false
Object.getPrototypeOf([]) === Array;           // false

[] instanceof Array.prototype;                 // TypeError
Array.prototype.isPrototypeOf([]);             // true
Object.getPrototypeOf([]) === Array.prototype; // true

虽然我没有解释,但为什么会发生这种奇怪的行为。双重包含的脚本是错误的根本原因。当我使用 Polymer 和 Webcomponents 时,多个组件包含相同的脚本。

通过将组件中的特定 <script ..> 标记移到主文档中,这些问题不再发生。

也许还有人知道,为什么会出现这样的错误?