【问题标题】:Get constructor name of object获取对象的构造函数名称
【发布时间】:2018-02-23 08:44:18
【问题描述】:

如何获取对象类的名称?我的意思是这个例子中的“过程”

我看到了两种获得它的方法。第一个是在这个类中写一个getter,比如

 getClassName(){return "Process"}

但是我想如果我尝试在不属于这个类并且没有这样的方法的对象中调用这个方法会出错。

第二个是使用object instanceof Process。但也许有一些方法可以让它变得更好、更正确?

【问题讨论】:

标签: javascript class ecmascript-6


【解决方案1】:

您可以通过constructor 上的name 获得它:

console.log(object.constructor.name);

例如,当您执行ex = new Example 时,在正常情况下使Example.prototype 成为所创建对象的原型(ex),并且该对象从该对象继承constructor 属性指回构造函数 (Example)。

我说“在正常情况下”是因为可以通过多种方式改变这些正常的关系。例如,代码可能已经用对象上的自己的属性 (ex.constructor = somethingElse;) 覆盖了 constructor 属性。要排除这种特定情况,您可以使用:

console.log(Object.getPrototypeOf(object).constructor.name);

活生生的例子:

class Example1 {
}
const e1 = new Example1();
console.log(e1.constructor.name); // "Example1"

class Example2 {
    constructor() {
        this.constructor = "I'm special";
    }
}
const e2 = new Example2();
console.log(Object.getPrototypeOf(e2).constructor.name); // "Example2"

指定 JavaScript 的 TC39 委员会成员很高兴在构建 then 和 catch 返回的新承诺时在 Promises 中使用实例的 constructor 属性(请参阅第 3 步 here 其中 @ 987654322@ 并从实例中读取constructor)(以及在其他一些地方),所以如果你也使用它,你就不会自己出去了。他们甚至不去实例的原型。

但是,是的,只是为了完整性,即使你去原型,它仍然有可能导致你误入歧途,因为原型的 constructor 属性也可以被弄乱:

class Example {
}
Example.prototype.constructor = Object; // Why would anyone do this? People are weird.
const e = new Example();
console.log(Object.getPrototypeOf(e).constructor.name); // "Object"

也可以在函数上重新定义name:

class Example {
}
// Why would someone do this? People are weird.
Object.defineProperty(Example, "name", {
    value: "flibberdeegibbit"
});
const e = new Example();
console.log(Object.getPrototypeOf(e).constructor.name); // "flibberdeegibbit"

所以...警告用户。


请注意,函数 name 属性在 ES2015 中是新的(class 语法也是如此)。如果您通过转译器使用class 语法,则它可能会或可能不会正确设置name。

【讨论】:

  • "如果你想有点偏执" ...你不会使用任何.constructor 或.name 属性:-)
  • @Bergi:嗯,有一定程度的偏执。 :-)
  • @T.J.Crowder 非常感谢!!
  • 据我所知,name 在某些浏览器中是只读的。答案没有提到name 将在缩小的代码中被破坏,这是绝对不能在客户端代码中使用它的。
  • 在某些 V8 版本中是不可配置的。即使不考虑旧版 Chrome,Android 浏览器中的支持也很难被忽视,这将产生难以检测和调试的令人讨厌的错误。这些是我默认不推荐 name 的充分理由 - 除非问题有 node.js 标签。
【解决方案2】:

如果确定object 源自此类/函数,则通常需要object instanceof Process。在某些情况下,情况可能并非如此。多个Process的出现可能是iframe、多个包版本等原因造成的。

常规函数类构造函数中已经存在name property。一个已知的陷阱是它会在缩小的代码中被破坏,所以它在浏览器 JS 中通常是无用的,它的使用可以被认为是一种反模式。 name 无法重新分配(在某些浏览器中),因此需要一个单独的属性来标识该类。

正确的方法是避免这个问题

但是我想如果我尝试在不属于这个类并且没有这样的方法的对象中调用这个方法会出错。

是使用getter:

class Process {
  get className() { return 'Process'; }
  ...
}

或属性:

class Process {
  ...
}
Process.prototype.className = 'Process';

因此,可能有多个 Process 类具有 Process className 标识符。这可能是可取的,也可能不是。而instanceof 将类实例与一个特定的类相关联。

【讨论】:

    【解决方案3】:

    使用name 属性如下:

    class Process {}
    
    console.log(Process.name);
    
    const process = new Process;
    
    console.log(process.constructor.name);

    这与使用函数的普通原型继承的工作方式相同。

    【讨论】:

      【解决方案4】:

      在对象上使用.constructor.name。每个对象的构造函数默认引用他的创建函数,该函数有一个name 属性。它返回函数的名称。

      class SomeClass {
      
      }
      
      const obj = new SomeClass();
      
      console.log(obj.constructor.name);

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-17
        • 1970-01-01
        • 2011-02-13
        • 1970-01-01
        • 1970-01-01
        • 2023-03-17
        • 1970-01-01
        • 2013-01-12
        相关资源
        最近更新 更多