获取ES6类实例的类名

时间:2015-03-27 21:31:29

标签: javascript ecmascript-6 traceur

有没有和谐的'从ES6类实例获取类名的方法?

以外
someClassInstance.constructor.name

目前我依靠Traceur实施。似乎Babel有Function.name的polyfill而Traceur没有。

总结一下:ES6 / ES2015 / Harmony中没有其他方式,ES中没有预期的ATM.Next。

它可以为未经管理的服务器端应用程序提供有用的模式,但在用于浏览器/桌面/移动设备的应用程序中是不需要的。

Babel uses core-js到polyfill Function.name,应该根据需要手动加载Traceur和TypeScript应用程序。

4 个答案:

答案 0 :(得分:166)

someClassInstance.constructor.name正是这样做的正确方法。运营商可能不支持这一点,但它是符合规范的标准方式。 (通过ClassDeclaration产生声明的函数的name属性在14.5.15中设置,步骤6。)

答案 1 :(得分:44)

正如@Domenic所说,使用someClassInstance.constructor.name。 @Esteban在评论中提及

  

someClassInstance.constructor是一个函数。所有函数都有name属性...

因此,要静态访问类名,请执行以下操作(这适用于我的Babel版本BTW。根据对@Domenic的评论,您的里程可能会有所不同)。

class SomeClass {
  constructor() {}
}

var someClassInstance = new SomeClass();
someClassInstance.constructor.name;      // === 'SomeClass'
SomeClass.name                           // === 'SomeClass'

<强>更新

Babel很好,但uglify / minification确实最终导致了我的问题。我正在制作游戏,并且正在创建池化Sprite资源的哈希值(其中键是函数名称)。缩小后,每个函数/类都被命名为t。这会杀死哈希。我在这个项目中使用Gulp,在阅读gulp-uglify docs后我发现有一个参数可以防止这个局部变量/函数名称发生变形。所以,在我的gulpfile中,我改变了

.pipe($.uglify()).pipe($.uglify({ mangle: false }))

这里有性能与可读性的权衡。不破坏名称将导致(略微)更大的构建文件(更多网络资源)和可能更慢的代码执行(需要引用 - 可能是BS)。另一方面,如果我保持相同,我必须在每个ES6类上手动定义getClassName - 在静态和实例级别。不,谢谢!

<强>更新

在评论中讨论之后,似乎避免使用.name约定来支持定义这些函数是一个很好的范例。它只需要几行代码,并且可以完全缩小代码的一般性和通用性(如果在库中使用)。所以我想我会改变主意并在我的课程上手动定义getClassName。谢谢@estus!。与直接变量访问相比,Getter / Setter通常是一个好主意,特别是在基于客户端的应用程序中。

class SomeClass {
  constructor() {}
  static getClassName(){ return 'SomeClass'; }
  getClassName(){ return SomeClass.getClassName(); }
}
var someClassInstance = new SomeClass();
someClassInstance.constructor.getClassName();      // === 'SomeClass' (static fn)
someClassInstance.getClassName();                  // === 'SomeClass' (instance fn)
SomeClass.getClassName()                           // === 'SomeClass' (static fn)

答案 2 :(得分:5)

直接从课程中获取课程名称

先前的回答解释说someClassInstance.constructor.name可以很好地工作,但是如果您需要以编程方式将类名转换为字符串,并且不想为此创建实例,请记住:

typeof YourClass === "function"

而且,由于每个函数都有一个name属性,所以使用类名获取字符串的另一种不错的方法是:

YourClass.name

下面是一个很好的例子,说明为什么这样做很有用。

加载Web组件

MDN documentation教我们,这就是您加载Web组件的方式:

customElements.define("your-component", YourComponent);

YourComponent是从HTMLElement扩展的类。由于在组件标签本身之后命名组件的类是一种好习惯,因此最好编写一个辅助函数,所有组件都可以使用该函数来注册自己。这是该函数:

function registerComponent(componentClass) {
    const componentName = upperCamelCaseToSnakeCase(componentClass.name);
    customElements.define(componentName, componentClass);
}

所以您要做的就是:

registerComponent(YourComponent);

这很不错,因为它比自己编写component标签要容易出错。总结一下,这是upperCamelCaseToSnakeCase()函数:

// converts `YourString` into `your-string`
function upperCamelCaseToSnakeCase(value) {
    return value
        // first char to lower case
        .replace(/^([A-Z])/, $1 => $1.toLowerCase())
        // following upper chars get preceded with a dash
        .replace(/([A-Z])/g, $1 => "-" + $1.toLowerCase());
}

答案 3 :(得分:1)

用于通天塔移植(在缩小之前)

如果您将Babel与@babel/preset-env一起使用,则可以保留类定义而无需将它们转换为函数(这会删除constructor属性)

您可以在babel.config / babelrc中删除与此配置之间的旧浏览器兼容性:

{
  "presets": [
    ["@babel/preset-env", {"targets": {"browsers": ["> 2%"]}}]
  ]
}

有关targets的更多信息:https://babeljs.io/docs/en/babel-preset-env#targets

用于缩小通天塔(在移植后)

看来目前没有简单的解决方案...我们需要研究如何处理排除问题。

相关问题