Create object from class name in JavasScript ECMAScript 6

前端 未结 6 1608
感动是毒
感动是毒 2020-11-22 15:46

I want create object factory using ES6 but old-style syntax doesn\'t work with new.

I have next code:

export class Column {}
export class Sequence {}         


        
相关标签:
6条回答
  • 2020-11-22 16:02

    I prefer this method:

    allThemClasses.js

    export class A {}
    export class B {}
    export class C {}
    

    script.js

    import * as Classes from './allThemClasses';
    
    const a = new Classes['A'];
    const b = new Classes['B'];
    const c = new Classes['C'];
    
    0 讨论(0)
  • 2020-11-22 16:04

    Don't put class names on that object. Put the classes themselves there, so that you don't have to rely on them being global and accessible (in browsers) through window.

    Btw, there's no good reason to make this factory a class, you would probably only instantiate it once (singleton). Just make it an object:

    export class Column {}
    export class Sequence {}
    export class Checkbox {}
    
    export const columnFactory = {
        specColumn: {
            __default: Column,    // <--
            __sequence: Sequence, // <--
            __checkbox: Checkbox  // <--
        },
        create(name, ...args) {
            let cls = this.specColumn[name] || this.specColumn.__default;
            return new cls(...args);
        }
    };
    
    0 讨论(0)
  • 2020-11-22 16:09

    There is a small & dirty way to do that:

    function createClassByName(name,...a) {
        var c = eval(name);
        return new c(...a);
    }
    

    You can now create a class like that:

    let c = createClassByName( 'Person', x, y );
    
    0 讨论(0)
  • 2020-11-22 16:09

    For those of you that are not using ES6 and want to know how you can create classes by using a string here is what I have done to get this to work.

    "use strict";
    
    class Person {
        constructor(x, y) {
            this.x = x;
            this.y = y;
        }
    }
    window.classes = {};
    window.classes.Person = Person;
    
    document.body.innerText = JSON.stringify(new window.classes["Person"](1, 2));
    

    As you can see the easiest way to do this is to add the class to an object.

    Here is the fiddle: https://jsfiddle.net/zxg7dsng/1/

    Here is an example project that uses this approach: https://github.com/pdxjohnny/dist-rts-client-web

    0 讨论(0)
  • 2020-11-22 16:21

    I know this is an old post, but recently I've had the same question about how to instance a class dynamically

    I'm using webpack so following the documentation there is a way to load a module dynamically using the import() function

    js/classes/MyClass.js

    class MyClass {
        test = null;
        constructor(param) {
            console.log(param)
            this.test = param;
        }
    }
    

    js/app.js

    var p = "example";
    var className = "MyClass";
    
    import('./classes/'+className).then(function(mod) {
        let myClass = new mod[className](p);
        console.log(myClass);
    }, function(failMsg) {
        console.error("Fail to load class"+className);
        console.error(failMsg);
    });
    

    Beware: this method is asynchronous and I can't really tell the performance cost for it, But it works perfectly on my simple program (worth a try ^^)

    Ps: To be fare I'm new to Es6 (a couple of days) I'm more a C++ / PHP / Java developer.

    I hope this helps anyone that come across this question and that is it not a bad practice ^^".

    0 讨论(0)
  • 2020-11-22 16:23

    The problem is that the classes are not properties of the window object. You can have an object with properties "pointing" to your classes instead:

    class Column {}
    class Sequence {}
    class Checkbox {}
    let classes = {
      Column,
      Sequence,
      Checkbox 
    }
    
    class ColumnFactory {
        constructor() {
            this.specColumn = {
                __default: 'Column',
                __sequence: 'Sequence',
                __checkbox: 'Checkbox'
            };
        }
    
        create(name) {
            let className = this.specColumn[name] ? this.specColumn[name] : this.specColumn['__default'];
            return new classes[className](name); // this line no longer throw error
        }
    }
    
    let factory = new ColumnFactory();
    let column = factory.create('userName');
    
    export {ColumnFactory, Column, Sequence, Checkbox};
    
    0 讨论(0)
提交回复
热议问题