获取ES6类实例的类名

Est*_*ask 142 javascript ecmascript-6 traceur

是否有任何"和谐"方法从ES6类实例中获取类名?以外

someClassInstance.constructor.name
Run Code Online (Sandbox Code Playgroud)

目前我指望Traceur的实施.似乎Babel有一个Function.namepolyfill ,而Traceur没有.

总而言之:ES6/ES2015/Harmony中没有其他方式,ES中没有预期的ATM.接下来.

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

巴别使用core-js到填充工具Function.name,应当手动加载Traceur和打字稿应用适当.

Dom*_*nic 189

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

  • 这就是我所害怕的.你知道任何合理的polyfill吗?我试图弄清楚巴贝尔是如何做到这一点但却收效甚微. (2认同)
  • @estus`someClassInstance.constructor`是一个函数。所有函数都有一个“名称”属性,该属性设置为其名称。这就是为什么通天塔不需要做任何事情。请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name (2认同)
  • @Esteban看来Babel持续推广core-js polyfill(包括Function.name的polyfill),这就是为什么一些Babel版本可以在所有浏览器中开箱即用的原因. (2认同)

Jam*_* L. 47

正如@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'
Run Code Online (Sandbox Code Playgroud)

更新

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

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

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

更新

在评论中讨论之后,似乎避免使用.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)
Run Code Online (Sandbox Code Playgroud)

  • 完全禁用重整不是一个好主意,因为重整会导致缩小很多.首先在客户端代码中使用主题并不是一个好主意,但是可以使用`reserved` Uglify选项保护类不受损坏(可以使用regexp或其他任何方式获取类列表). (3认同)

Luc*_*iva 7

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

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

typeof YourClass === "function"
Run Code Online (Sandbox Code Playgroud)

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

YourClass.name
Run Code Online (Sandbox Code Playgroud)

接下来的例子很好地说明了为什么这样做很有用。

加载网页组件

正如MDN文档所教导的,这是您加载Web组件的方式:

customElements.define("your-component", YourComponent);
Run Code Online (Sandbox Code Playgroud)

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

function registerComponent(componentClass) {
    const componentName = upperCamelCaseToSnakeCase(componentClass.name);
    customElements.define(componentName, componentClass);
}
Run Code Online (Sandbox Code Playgroud)

因此,您需要做的是:

registerComponent(YourComponent);
Run Code Online (Sandbox Code Playgroud)

很好,因为它比自己编写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());
}
Run Code Online (Sandbox Code Playgroud)