ES6 动态类名

问题描述 投票:0回答:6

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

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

// test: 
let itsName =  (new C()).constructor.name;
// itsName === 'TheName' -> true

31
投票

有一个非常简单的方法:

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

这里是演示。

它使用对象文字来定义具有所需名称的字段,该字段将保存新类。这会导致新类自动获取所需的名称。完成后,我们提取新类并返回它。

请注意对象文字周围的括号,这样大括号就不会被误认为是代码块

(...) => {...}

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

const myClass = {[name]: class {
    ...
}}[name];

24
投票

对于您想要实现的目标,可能有更好的解决方案,但是您可以将类表达式分配给对象:

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

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


4
投票

为了进一步玩动态类名和动态继承,当使用 babel 时,你可以这样做:

    function withname(name, _parent) {
        return class MyDinamicallyNamedClass extends (_parent||Object) {
            static get name() { return name || _parent.name }
        }
    }

4
投票

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

eval
:

~function() {
    const name = "Lorem"

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

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

注意,必须与

var
。在
let
内使用
const
class
和普通
eval
不起作用。

另一种方式

Function
:

~function() {
    const name = "Lorem"

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

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

Sitenote:您可以将范围变量传递到

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"
}()

0
投票

我可以建议另一种方法,只是异步,但它有效:

let protoExtend = function ( className, extendsFrom = Array ) {

    return new Promise( function ( done, fail ) {
        
        const src = URL.createObjectURL(
            new Blob( [`
                self.${className}(
                    class ${className} extends ${extendsFrom.name} {}
                );`
            ] )
        );

        self[ className ] = function ( prototype ){
            URL.revokeObjectURL(src);
            delete self[ className ];
            return done( prototype );
        };

        document.head.append( Object.assign(
            document.createElement("script"), { src }
        ));
        
    });
    
};

使用父类和新子类的名称触发类构造函数:

let myClass = await protoExtend("HelloWorld", String);

现在我们有了我们想要的:动态创建的子级,无需任何评估:

new myClass('test');

结果也可以显示在控制台上: enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.