获取 ES6 class 实例的 class 名称
Get the class name of ES6 class instance
是否有任何 'harmonious' 方法从 ES6 class 实例中获取 class 名称?除了
someClassInstance.constructor.name
目前我指望 Traceur 实现。 Babel 似乎有 Function.name
的 polyfill,而 Traceur 没有。
总而言之:在ES6/ES2015/Harmony没有别的办法,在ES.Next.
也没有ATM。
它可能为未缩小的服务器端应用程序提供有用的模式,但在用于 browser/desktop/mobile 的应用程序中不需要。
Babel uses core-js
to polyfill Function.name
,应酌情为 Traceur 和 TypeScript 应用程序手动加载。
someClassInstance.constructor.name
正是执行此操作的正确方法。转译器可能不支持这一点,但这是规范中的标准方式。 (通过 ClassDeclaration productions 声明的函数的 name
属性 在步骤 6 14.5.15 中设置。)
正如@Domenic 所说,使用someClassInstance.constructor.name
。 @Esteban 在评论中提到
someClassInstance.constructor
is a Function. All Functions have a name
property...
因此,要静态访问 class 名称,请执行以下操作(顺便说一句,这适用于我的 Babel 版本。根据 @Domenic 上的评论,您的情况可能会有所不同)。
class SomeClass {
constructor() {}
}
var someClassInstance = new SomeClass();
someClassInstance.constructor.name; // === 'SomeClass'
SomeClass.name // === 'SomeClass'
更新
Babel 很好,但 uglify/minification 确实给我带来了麻烦。我正在制作游戏,并正在创建池化 Sprite 资源的哈希(其中键是函数名称)。缩小后,每个 function/class 被命名为 t
。这会杀死哈希。我在这个项目中使用 Gulp
,在阅读 gulp-uglify docs 之后,我发现有一个参数可以防止这个本地 variable/function 名称重整发生。所以,在我的 gulpfile 中我改变了
.pipe($.uglify())
到 .pipe($.uglify({ mangle: false }))
这里需要权衡性能与可读性。不修改名称将导致(稍微)更大的构建文件(更多网络资源)和可能更慢的代码执行(需要引用 - 可能是 BS)。另一方面,如果我保持不变,我将不得不在每个 ES6 class 上手动定义 getClassName
- 在静态和实例级别。不,谢谢!
更新
经过评论中的讨论,似乎避免 .name
约定而支持定义这些函数是一个很好的范例。它只需要几行代码,并且允许完全缩小和通用代码(如果在库中使用)。所以我想我改变了主意,将在我的 classes 上手动定义 getClassName
。谢谢@estus!。 Getter/Setters 与直接变量访问相比通常是个好主意,尤其是在基于客户端的应用程序中。
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)
直接从class
获取class名字
之前的答案解释说 someClassInstance.constructor.name
工作正常,但是如果您需要以编程方式将 class 名称转换为字符串并且不想为此创建一个实例,请记住:
typeof YourClass === "function"
而且,由于每个函数都有一个 name
属性,另一种获取带有 class 名称的字符串的好方法是:
YourClass.name
下面是一个很好的例子,说明了为什么这是有用的。
正在加载网络组件
正如 MDN documentation 教导我们的那样,这就是加载 Web 组件的方式:
customElements.define("your-component", YourComponent);
其中 YourComponent
是从 HTMLElement
延伸而来的 class。由于在组件标签本身之后命名组件的 class 被认为是一种很好的做法,因此编写一个所有组件都可以用来注册自己的辅助函数会很好。所以这是函数:
function registerComponent(componentClass) {
const componentName = upperCamelCaseToSnakeCase(componentClass.name);
customElements.define(componentName, componentClass);
}
所以你需要做的就是:
registerComponent(YourComponent);
这很好,因为它比自己编写组件标签更不容易出错。总结一下,这是 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());
}
用于 babel 转译(缩小之前)
如果您将 Babel 与 @babel/preset-env
一起使用,则可以保留 类 定义而不将它们转换为函数(这会删除 constructor
属性)
您可以在 babel.config / babelrc
:
中删除一些与此配置的旧浏览器兼容性
{
"presets": [
["@babel/preset-env", {"targets": {"browsers": ["> 2%"]}}]
]
}
More informations about targets
: https://babeljs.io/docs/en/babel-preset-env#targets
用于 babel 缩小(转译后)
现在看来没有简单的解决方案...我们需要考虑修改排除项。
是否有任何 'harmonious' 方法从 ES6 class 实例中获取 class 名称?除了
someClassInstance.constructor.name
目前我指望 Traceur 实现。 Babel 似乎有 Function.name
的 polyfill,而 Traceur 没有。
总而言之:在ES6/ES2015/Harmony没有别的办法,在ES.Next.
也没有ATM。它可能为未缩小的服务器端应用程序提供有用的模式,但在用于 browser/desktop/mobile 的应用程序中不需要。
Babel uses core-js
to polyfill Function.name
,应酌情为 Traceur 和 TypeScript 应用程序手动加载。
someClassInstance.constructor.name
正是执行此操作的正确方法。转译器可能不支持这一点,但这是规范中的标准方式。 (通过 ClassDeclaration productions 声明的函数的 name
属性 在步骤 6 14.5.15 中设置。)
正如@Domenic 所说,使用someClassInstance.constructor.name
。 @Esteban 在评论中提到
someClassInstance.constructor
is a Function. All Functions have aname
property...
因此,要静态访问 class 名称,请执行以下操作(顺便说一句,这适用于我的 Babel 版本。根据 @Domenic 上的评论,您的情况可能会有所不同)。
class SomeClass {
constructor() {}
}
var someClassInstance = new SomeClass();
someClassInstance.constructor.name; // === 'SomeClass'
SomeClass.name // === 'SomeClass'
更新
Babel 很好,但 uglify/minification 确实给我带来了麻烦。我正在制作游戏,并正在创建池化 Sprite 资源的哈希(其中键是函数名称)。缩小后,每个 function/class 被命名为 t
。这会杀死哈希。我在这个项目中使用 Gulp
,在阅读 gulp-uglify docs 之后,我发现有一个参数可以防止这个本地 variable/function 名称重整发生。所以,在我的 gulpfile 中我改变了
.pipe($.uglify())
到 .pipe($.uglify({ mangle: false }))
这里需要权衡性能与可读性。不修改名称将导致(稍微)更大的构建文件(更多网络资源)和可能更慢的代码执行(需要引用 - 可能是 BS)。另一方面,如果我保持不变,我将不得不在每个 ES6 class 上手动定义 getClassName
- 在静态和实例级别。不,谢谢!
更新
经过评论中的讨论,似乎避免 .name
约定而支持定义这些函数是一个很好的范例。它只需要几行代码,并且允许完全缩小和通用代码(如果在库中使用)。所以我想我改变了主意,将在我的 classes 上手动定义 getClassName
。谢谢@estus!。 Getter/Setters 与直接变量访问相比通常是个好主意,尤其是在基于客户端的应用程序中。
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)
直接从class
获取class名字之前的答案解释说 someClassInstance.constructor.name
工作正常,但是如果您需要以编程方式将 class 名称转换为字符串并且不想为此创建一个实例,请记住:
typeof YourClass === "function"
而且,由于每个函数都有一个 name
属性,另一种获取带有 class 名称的字符串的好方法是:
YourClass.name
下面是一个很好的例子,说明了为什么这是有用的。
正在加载网络组件
正如 MDN documentation 教导我们的那样,这就是加载 Web 组件的方式:
customElements.define("your-component", YourComponent);
其中 YourComponent
是从 HTMLElement
延伸而来的 class。由于在组件标签本身之后命名组件的 class 被认为是一种很好的做法,因此编写一个所有组件都可以用来注册自己的辅助函数会很好。所以这是函数:
function registerComponent(componentClass) {
const componentName = upperCamelCaseToSnakeCase(componentClass.name);
customElements.define(componentName, componentClass);
}
所以你需要做的就是:
registerComponent(YourComponent);
这很好,因为它比自己编写组件标签更不容易出错。总结一下,这是 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());
}
用于 babel 转译(缩小之前)
如果您将 Babel 与 @babel/preset-env
一起使用,则可以保留 类 定义而不将它们转换为函数(这会删除 constructor
属性)
您可以在 babel.config / babelrc
:
{
"presets": [
["@babel/preset-env", {"targets": {"browsers": ["> 2%"]}}]
]
}
More informations about
targets
: https://babeljs.io/docs/en/babel-preset-env#targets
用于 babel 缩小(转译后)
现在看来没有简单的解决方案...我们需要考虑修改排除项。