【问题标题】:Why does instanceof a class return false even though the constructor is in its prototype chain?为什么即使构造函数在其原型链中,类的 instanceof 也会返回 false?
【发布时间】:2018-11-28 15:12:58
【问题描述】:

在 NodeJS 应用程序中,我试图检查传递给函数的值是否是特定类的实例,但是在模块之间使用 instanceof 以及检查类的相等性时,我得到了意外的行为。

endpoint.js

import SomeClass from 'utils/class';
import SomeModel from 'models/model';

const model = SomeModel.findOne({id: 'abc'});
const values = {a: 'b'};
const classInstance = new SomeClass({id: 'def'});

classInstance instanceof SomeClass //returns true
Object.getPrototypeOf(classInstance) //returns SomeClass {}

model.update(values, { a: classInstance, b: SomeClass });

当 classInstance 传递给更新函数时,我看到了意外的行为。

调用 Object.getPrototypeOf(a) 会返回 SomeClass,a.constructor.name 也是如此。但是,a instanceof SomeClass 返回假。

此外,仅检查导入的类和传递给函数的类之间的相等性会返回 false。

require.resolve('utils/class') 为两个导入返回相同的路径。

models/model.js

import SomeClass from 'utils/class';

class Model {
  async update(values, injections) {
    const { a, b } = injections;

    // checking instance
    a.constructor.name //returns SomeClass
    Object.getPrototypeOf(a) //returns SomeClass {}
    a instanceof SomeClass; //returns false

    // checking class
    b === SomeClass; //returns false
  }
}

我希望 b === SomeClass 会返回 true,就像 a instanceof SomeClass 也应该返回 true,除非我遗漏了什么。感谢您的帮助。

utils/class.js

export default class SomeClass {
  constructor(foo) {
    this.bar = foo;
  }
}

编辑:代码正在使用@std/esm 进行转译。 NODE_PATH=./src/ nodemon -r @std/esm src/server.js

【问题讨论】:

  • 如果我使用new Model 而不是SomeModel.findOne() 创建一个实例,我会得到预期的结果。 jsfiddle.net/mptbhu0c
  • 缺少太多信息。你最好提供一个stackoverflow.com/help/mcve
  • num8er 可能有它。虽然它们都解析为字符串“SomeClass”,但它们可能指向已定义的 SomeClass 模型的不同实例,因此它们实际上并不是同一件事。
  • 转译几乎 ES 化的代码有什么好处?我个人不喜欢转译。那些等待重读,每次我改变一些东西时编译。最新的 nodejs 有类,异步/等待 - 其他东西差不多:import vs require 没什么特别的。那么为什么要把几乎复杂的 JS 代码复杂化呢?
  • 我指的是类定义的实例。你能发帖utils/class.js吗? github.com/standard-things/esm/issues/633 相关吗?

标签: javascript node.js instanceof


【解决方案1】:

是因为SomeClass 实例被定义了多次(由于转译器等)?考虑这个将返回 false 的代码:

(function() {

    class Foo {};

    class Bar {
        check(a) {
            console.log(a instanceof Foo);
        }
    };

    window.bar = new Bar();

})();

(function() {
    class Foo {};
    const foo = new Foo();
    window.bar.check(foo);
})();

与 Foo、Bar 等相比,仅在全局范围内定义了 1 次(require() 应该缓存这些依赖项,因此您不应该遇到这种行为):

class Foo {};

class Bar {
    check(a) {
        console.log(a instanceof Foo);
    }
};

const foo = new Foo();
Bar.prototype.check(foo);

在 std/esm 项目中有一个 issue 有人正在经历同样的事情。我不使用那个库,所以没有具体的想法。

或者我可能会离开。

【讨论】:

    【解决方案2】:

    cmets 中的查理为我们指明了正确的方向。

    https://github.com/DaveStein/esm-bug 正在复制此内容,我已经在 Charlie 报告的问题 https://github.com/standard-things/esm/issues/633 中指出了这一点。

    【讨论】:

    • 很高兴我能帮上忙!祝你好运。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-15
    • 1970-01-01
    • 2015-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多