Javascript 获取 ES6 类实例的类名
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29310530/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get the class name of ES6 class instance
提问by Estus Flask
Are there any 'harmonious' ways to get the class name from ES6 class instance? Other than
是否有任何“和谐”的方法可以从 ES6 类实例中获取类名?以外
someClassInstance.constructor.name
Currently I'm counting on Traceur implementation. And it seems that Babel has a polyfill for Function.namewhile Traceur doesn't.
目前我指望 Traceur 实现。似乎 Babel 有一个Function.namepolyfill ,而 Traceur 没有。
To sum it all up: there was no other way in ES6/ES2015/Harmony, and nothing is expected ATM in ES.Next.
总而言之:在 ES6/ES2015/Harmony 中没有其他方式,在 ES.Next 中没有预期的 ATM。
It may provide useful patterns for unminified server-side applications but is unwanted in applications meant for browser/desktop/mobile.
它可能为未缩小的服务器端应用程序提供有用的模式,但在用于浏览器/桌面/移动设备的应用程序中是不需要的。
Babel uses core-jsto polyfill Function.name, it should be loaded manually for Traceur and TypeScript applications as appropriate.
巴别用途core-js来填充工具Function.name,应当手动Traceur和打字稿应用适当装载。
回答by Domenic
someClassInstance.constructor.nameis exactly the correct way to do this. Transpilers may not support this, but it is the standard way per the specification. (The nameproperty of functions declared via ClassDeclaration productions is set in 14.5.15, step 6.)
someClassInstance.constructor.name正是这样做的正确方法。转译器可能不支持这一点,但这是规范中的标准方式。(name通过 ClassDeclaration 产生式声明的函数的属性在14.5.15 的第 6 步中设置。)
回答by James L.
As @Domenic says, use someClassInstance.constructor.name. @Esteban mentions in the comments that
正如@Domenic 所说,使用someClassInstance.constructor.name. @Esteban 在评论中提到
someClassInstance.constructoris a Function. All Functions have anameproperty...
someClassInstance.constructor是一个函数。所有函数都有一个name属性...
Thus, to access the class name statically, do the following (this works with my Babel version BTW. According to the comments on @Domenic your mileage may vary).
因此,要静态访问类名,请执行以下操作(这适用于我的 Babel 版本 BTW。根据 @Domenic 上的评论,您的里程可能会有所不同)。
class SomeClass {
constructor() {}
}
var someClassInstance = new SomeClass();
someClassInstance.constructor.name; // === 'SomeClass'
SomeClass.name // === 'SomeClass'
Update
更新
Babel was fine, but uglify/minification did end up causing me problems. I am making a game, and am creating a hash of pooled Sprite resources (where the key is the function name). After minification, every function/class was named t. This kills the hash. I am using Gulpin this project, and after reading the gulp-uglify docsI discovered there is a parameter to prevent this local variable/function name mangling from happening. So, in my gulpfile I changed
Babel 很好,但丑化/缩小最终给我带来了问题。我正在制作一个游戏,并且正在创建一个池化 Sprite 资源的散列(其中键是函数名称)。缩小后,每个函数/类都被命名为t. 这会杀死哈希。我Gulp在这个项目中使用,在阅读了gulp-uglify 文档后,我发现有一个参数可以防止这个局部变量/函数名称重整的发生。所以,在我的 gulpfile 中我改变了
.pipe($.uglify())to .pipe($.uglify({ mangle: false }))
.pipe($.uglify())到 .pipe($.uglify({ mangle: false }))
There is a trade-off of performance vs readability here. Not mangling the names will result in a (slightly) larger build file (more network resources) and potentially slower code execution (citation needed - may be BS). On the other hand, if I kept it the same I would have to manually define getClassNameon every ES6 class - at a static and instance level. No thanks!
这里需要权衡性能与可读性。不修改名称将导致(稍微)更大的构建文件(更多网络资源)和可能更慢的代码执行(需要引用 - 可能是废话)。另一方面,如果我保持不变,我将不得不getClassName在每个 ES6 类上手动定义- 在静态和实例级别。不,谢谢!
Update
更新
After the discussion in the comments, it seems like avoiding the .nameconvention in favor of defining those functions is a good paradigm. It only takes a few lines of code, and will allow full minification and generality of your code (if used in a library). So I guess I change my mind and will manually define getClassNameon my classes. Thanks @estus!. Getter/Setters are usually a good idea compared to direct variable access anyways, especially in a client based application.
在评论中的讨论之后,似乎避免.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)
回答by Lucio Paiva
Getting class name directly from class
直接从类中获取类名
Previous answers explained that someClassInstance.constructor.nameworks just fine, but if you need to programmatically convert class name into a string and don't want to create an instance just for that, remember that:
以前的答案解释说someClassInstance.constructor.name工作得很好,但是如果您需要以编程方式将类名转换为字符串并且不想为此创建实例,请记住:
typeof YourClass === "function"
And, since every function has a nameproperty, another nice way to get a string with your class name is to just do:
而且,由于每个函数都有一个name属性,另一种使用类名获取字符串的好方法是:
YourClass.name
What follows is a good example of why this is useful.
下面是一个很好的例子,说明为什么这很有用。
Loading web components
加载 Web 组件
As the MDN documentationteaches us, this is how you load a web component:
正如MDN 文档告诉我们的那样,这是加载 Web 组件的方式:
customElements.define("your-component", YourComponent);
Where YourComponentis a class extending from HTMLElement. Since it is considered good practice to name your component's class after the component tag itself, it would be nice to write a helper function that all your components could use to register themselves. So here's is that function:
从哪里YourComponent扩展的类HTMLElement。由于在组件标签本身之后命名组件的类被认为是一种很好的做法,因此最好编写一个所有组件都可以用来注册自己的辅助函数。所以这是那个函数:
function registerComponent(componentClass) {
const componentName = upperCamelCaseToSnakeCase(componentClass.name);
customElements.define(componentName, componentClass);
}
So all you need to do is:
所以你需要做的就是:
registerComponent(YourComponent);
Which is nice because it's less error-prone than writing the component tag yourself. To wrap it up, this is the upperCamelCaseToSnakeCase()function:
这很好,因为它比自己编写组件标签更不容易出错。总结一下,这是upperCamelCaseToSnakeCase()函数:
// converts `YourString` into `your-string`
function upperCamelCaseToSnakeCase(value) {
return value
// first char to lower case
.replace(/^([A-Z])/, => .toLowerCase())
// following upper chars get preceded with a dash
.replace(/([A-Z])/g, => "-" + .toLowerCase());
}
回答by Ifnot
For babel transpilation (before minification)
用于 babel 转译(缩小前)
If you are using Babel with @babel/preset-env, it is possible to keep classes definitions without converting them to functions (whitch remove the constructorproperty)
如果您使用 Babel with @babel/preset-env,则可以保留类定义而不将它们转换为函数(删除constructor属性)
You can drop some old browser compatibility with this configuration in your babel.config / babelrc:
您可以在以下配置中删除一些与此配置的旧浏览器兼容性babel.config / babelrc:
{
"presets": [
["@babel/preset-env", {"targets": {"browsers": ["> 2%"]}}]
]
}
More informations about
targets: https://babeljs.io/docs/en/babel-preset-env#targets
更多信息
targets:https: //babeljs.io/docs/en/babel-preset-env#targets
For babel minification (after transpilation)
用于 babel 缩小(转译后)
It looks there is no easy solution right now ... We need to look at mangling exclusions.
看起来现在没有简单的解决方案......我们需要看看重整排除。

