Erstellen Sie ein Objekt aus dem Klassennamen in JavaScript ECMAScript 6

Lesezeit: 4 Minuten

Erstellen Sie ein Objekt aus dem Klassennamen in JavaScript ECMAScript
Serhij Popow

Ich möchte eine Objektfabrik mit ES6 erstellen, aber die Syntax im alten Stil funktioniert nicht mit neu.

Ich habe den nächsten Code:

export class Column {}
export class Sequence {}
export class Checkbox {}

export 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 window[className](name); // this line throw error
    }
}

let factory = new ColumnFactory();
let column = factory.create('userName');

Was mache ich falsch?

  • FYI, die manuell codierte ES5-Version davon funktioniert hier: jsfiddle.net/jfriend00/4x45gqLt. Es lohnt sich wahrscheinlich, sich anzusehen, was babeljs produziert, um zu sehen, was anders ist. Offenbar Column ist nicht global (und somit nicht auf der window Objekt), aber der generierte ES5-Code würde es Ihnen sicher zeigen.

    – jfriend00

    2. August 2015 um 22:09 Uhr


  • Äh, window[className] hat nie zuverlässig funktioniert.

    – Bergi

    3. August 2015 um 14:23 Uhr

Geben Sie diesem Objekt keine Klassennamen. Legen Sie die Klassen selbst dort ab, damit Sie sich nicht darauf verlassen müssen, dass sie global und (in Browsern) durch zugänglich sind window.

Übrigens gibt es keinen guten Grund, diese Factory zu einer Klasse zu machen, Sie würden sie wahrscheinlich nur einmal instanziieren (Singleton). Machen Sie es einfach zu einem Objekt:

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);
    }
};

  • Eigentlich ein tolles Fabrikbeispiel, habe es in meinem Projekt verwendet 🙂

    – Oleg Abrazhaev

    3. März 2019 um 18:00 Uhr


Es gibt einen kleinen und schmutzigen Weg, das zu tun:

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

Sie können jetzt eine Klasse wie folgt erstellen:

let c = createClassByName( 'Person', x, y );

  • Ich mag diese Evaluierungslösung

    – Dee

    29. Mai 2017 um 4:59 Uhr

  • +1 auch von mir. Ich weiß, dass jeder eval verurteilt, aber solange Sie die volle Kontrolle über die möglichen Werte haben, ist es die einfachste und flexibelste Lösung.

    – Iarwa1n

    21. August 2018 um 19:01 Uhr

  • Ich mag dieses eval, aber jetzt haben alle ein Problem, können keine Variablen mit eval in der es6-Klassenmethode erstellen

    – Dee

    4. September 2018 um 11:17 Uhr

  • Ich denke, es besteht ein Sicherheitsrisiko bei der Verwendung von eval() developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/….

    – Frederick G. Sandalo

    16. Juli 2020 um 15:37 Uhr

  • eval ist genial

    – Benutzer3413723

    6. Januar um 21:36 Uhr

Erstellen Sie ein Objekt aus dem Klassennamen in JavaScript ECMAScript
Amit

Das Problem ist, dass die Klassen keine Eigenschaften des Fensterobjekts sind. Sie können stattdessen ein Objekt mit Eigenschaften haben, das auf Ihre Klassen “zeigt”:

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};

  • Ist der Column Konstruktor nicht global?

    – jfriend00

    2. August 2015 um 22:04 Uhr

  • Anscheinend nicht in babeljs (Kann Repl nicht posten, zu lange)

    – Amit

    2. August 2015 um 22:05 Uhr

Für diejenigen unter Ihnen, die ES6 nicht verwenden und wissen möchten, wie Sie Klassen mithilfe einer Zeichenfolge erstellen können, habe ich Folgendes getan, um dies zum Laufen zu bringen.

"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));

Wie Sie sehen können, besteht die einfachste Möglichkeit darin, die Klasse einem Objekt hinzuzufügen.

Hier ist die Geige:
https://jsfiddle.net/zxg7dsng/1/

Hier ist ein Beispielprojekt, das diesen Ansatz verwendet:
https://github.com/pdxjohnny/dist-rts-client-web

Ich bevorzuge diese Methode:

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'];

1646265909 579 Erstellen Sie ein Objekt aus dem Klassennamen in JavaScript ECMAScript
Karl Tarife

Ich weiß, dass dies ein alter Beitrag ist, aber kürzlich hatte ich die gleiche Frage, wie man eine Klasse dynamisch instanziiert

Ich benutze Webpaket also nach dem Dokumentation Es gibt eine Möglichkeit, ein Modul mithilfe von dynamisch zu laden importieren() Funktion

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);
});

In acht nehmen: Diese Methode ist asynchron und ich kann die Leistungskosten dafür nicht wirklich sagenAber es funktioniert perfekt auf meinem einfachen Programm (einen Versuch wert ^^)

PS: Ich bin neu bei Es6 (ein paar Tage) Ich bin eher ein C++ / PHP / Java-Entwickler.

Ich hoffe, das hilft jedem, der auf diese Frage stößt, und das ist keine schlechte Praxis ^^”.

917540cookie-checkErstellen Sie ein Objekt aus dem Klassennamen in JavaScript ECMAScript 6

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy