ES6 动态类名

IT技术 javascript class ecmascript-6
2021-03-07 00:25:05

我一直在试验 ES6 类,想知道您是否可以动态更改类名?例如

class [Some dynamic name] {}; 
6个回答
let C = class
{ // ...
}
Object.defineProperty (C, 'name', {value: 'TheName'});

// test: 
let itsName =  (new C()).constructor.name;
// itsName === 'TheName' -> true
我相信这是正确的答案。 Object.defineProperty(C, 'name', ...)作品而C.name = ...抛出Script Error: "name" is read-only(至少在Firefox)。
2021-04-23 00:25:05
是的,这是截至当前日期的正确答案。在类定义本身中没有办法做到这一点
2021-04-25 00:25:05
这应该是正确答案,接受的答案类没有名称。
2021-05-01 00:25:05
您好,如果您提供代码的解释会很有帮助。
2021-05-03 00:25:05
Object.defineProperty()应该允许只读属性的修改,或者是仅仅是不是应该有一个实现怪癖?
2021-05-14 00:25:05

有一个非常简单的方法来做到这一点:

const nameIt = (name, cls) => ({[name] : class extends cls {}})[name];

是演示。

它使用对象字面量来定义一个具有所需名称的字段,该字段将包含一个新类。这会导致新类自动获得所需的名称。完成后,我们提取该新类并将其返回。

注意对象字面量周围的括号,以免花括号被误认为是代码块(...) => {...}

当然,将现有类放入命名字段不会更改该类,因此这仅在您创建新类时才有效。如果您只需要在定义要命名的类的地方使用动态名称,则可以删除额外的继承,然后继续:

const myClass = {[name]: class {
    ...
}}[name];
如果我们有一个将类称为“this”的静态方法,则此技术将不起作用。示例: static create = (args) => new this(args); 在这种情况下,名称将为“_class”
2021-04-30 00:25:05
我们也可以添加方法吗?并再次添加新属性?
2021-05-14 00:25:05

对于您想要实现的任何目标,可能都有更好的解决方案,但您可以为对象分配一个类表达式:

let classes = {};
classes[someName] = class { ... };

这在 ES2015 中并没有真正改变:如果你想创建一个动态命名的绑定,你必须使用一个对象或其他一些映射来代替。

如何将装饰器添加到这样的类表达式中?
2021-04-19 00:25:05
我再次检查,我有一个自定义的 babel-transform,不小心禁用了它。
2021-04-30 00:25:05
或者等等,那只是在做的时候 {[someName]: class {…}}
2021-05-01 00:25:05
@FabianZeindl:没有理由这不应该起作用,因为这个标准甚至在 ES6 之前就已经存在了class(当然value除外 )。
2021-05-03 00:25:05
实际上,随着 ES6 的改变,类的.name现在是someName.
2021-05-15 00:25:05

为了更深入地使用动态类名和动态继承,在使用 babel 时,您可以执行以下操作:

    function withname(name, _parent) {
        return class MyDinamicallyNamedClass extends (_parent||Object) {
            static get name() { return name || _parent.name }
        }
    }
是的,但我认为他的观点是       ( MyDinamicallyNamedClass instanceof _parent) 返回真 \n       (顺便说一句,这不是你动态拼写的方式,lOlz)
2021-04-18 00:25:05
但控制台仍然输出 class MyDinamicallyNamedClass ...
2021-05-05 00:25:05

一种方法,即使不理想,也很简单eval

~function() {
    const name = "Lorem"

    eval(`
        var ${name} = class ${name} {} 
    `)

    console.log(Lorem) // class Lorem {}
}()

请注意,它必须与var. 在里面使用let, const, 和 plainclasseval行不通的。

另一种方式Function

~function() {
    const name = "Lorem"

    const c = new Function(`
        return class ${name} {}
    `)()

    console.log(c) // class Lorem {}
}()

站点注意:您可以将范围变量传递到Function并在其中使用它们:

~function() {
    const name = "Lorem"
    const val = "foo"

    const Class = new Function('val', `
        return class ${name} {
            constructor() {
                console.log( val )
            }
        }
    `)( val )

    console.log(Class) // class Lorem {}
    new Class // "foo"
}()
请注意,使用Function这种方式也eval具有相同的风险。
2021-04-15 00:25:05
如果您将 3rd-party 代码粘贴在Functionor 中,那只是一个问题eval如果您拥有粘贴在其中的代码,这不是问题(fe 代码字符串在与Functionor相同的范围内生成eval,没有来自外部的输入)。
2021-04-15 00:25:05
我已经更新了我的示例以使用闭包(很像module)。
2021-05-03 00:25:05
@eyelidlessness这只是一个问题,如果你里面坚持第三方代码Functioneval如果您拥有粘贴在其中的代码,这不是问题(fe 代码字符串在与Functionor相同的范围内生成eval,没有来自外部的输入)。正如您在我的示例中看到的,字符串是就地生成的,这是完全安全的(假设我的代码在module内部,变量不可能从外部修改)。
2021-05-05 00:25:05
仍然值得指出,因为人们倾向于采用代码示例并对其进行扩展。对于不太熟悉它的工作原理的人来说,它可能不是很明显eval我强烈建议您为此添加警告。
2021-05-13 00:25:05