Erstellen Sie ein Objekt aus dem Klassennamen in JavaScript ECMAScript 6
Lesezeit: 4 Minuten
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
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.
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'];
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 ^^”.
9175400cookie-checkErstellen Sie ein Objekt aus dem Klassennamen in JavaScript ECMAScript 6yes
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 derwindow
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