Create object from class name in JavasScript ECMAScript 6
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);
}
};
Create an instance of a class in ES6 with a dynamic name?
There are a few ways you can accomplish this...
1. Proxy Class
Following from @thefourtheye's example of maintaining a mapping of name to class, you could have a class whose job is to take the name of the desired class and proxy its instantiation:
[ See it working ]
Define your classes
// ClassOne.js
export class ClassOne {
constructor () {
console.log("Hi from ClassOne");
}
}
// ClassTwo.js
export class ClassTwo {
constructor (msg) {
console.log(`${msg} from ClassTwo`);
}
}
Define the proxy class (e.g. DynamicClass
)
import ClassOne from './ClassOne';
import ClassTwo from './ClassTwo';
// Use ES6 Object Literal Property Value Shorthand to maintain a map
// where the keys share the same names as the classes themselves
const classes = {
ClassOne,
ClassTwo
};
class DynamicClass {
constructor (className, opts) {
return new classes[className](opts);
}
}
export default DynamicClass;
Example usage
import DynamicClass from './DynamicClass';
new DynamicClass('ClassOne'); //=> "Hi from ClassOne"
new DynamicClass('ClassTwo', 'Bye'); //=> "Bye from ClassTwo"
2. Factory Function
Use a function that performs a lookup against an object of class name -> class mappings and returns reference to the class, which we can then instantiate as usual.
Define the factory function
import ClassOne from './ClassOne';
import ClassTwo from './ClassTwo';
const classes = { ClassOne, ClassTwo };
export default function dynamicClass (name) {
return classes[name];
}
Example usage
import dynamicClass from './dynamicClass'
const ClassOne = dynamicClass('ClassOne') // Get the ClassOne class
new ClassOne(args) // Create an instance of ClassOne
ES6 class instance from string
Only global variables are put into window
automatically.
Create an object that maps from class names to classes:
const classMap = {
"MyClass": MyClass,
"MyClass2": MyClass2,
...
};
Then use classMap[name](params)
rather than window[name](params)
.
How to get a JavaScript object's class?
There's no exact counterpart to Java's getClass()
in JavaScript. Mostly that's due to JavaScript being a prototype-based language, as opposed to Java being a class-based one.
Depending on what you need getClass()
for, there are several options in JavaScript:
typeof
instanceof
obj.
constructor
func.
prototype
,proto
.isPrototypeOf
A few examples:
function Foo() {}
var foo = new Foo();
typeof Foo; // == "function"
typeof foo; // == "object"
foo instanceof Foo; // == true
foo.constructor.name; // == "Foo"
Foo.name // == "Foo"
Foo.prototype.isPrototypeOf(foo); // == true
Foo.prototype.bar = function (x) {return x+x;};
foo.bar(21); // == 42
Note: if you are compiling your code with Uglify it will change non-global class names. To prevent this, Uglify has a --mangle
param that you can set to false is using gulp or grunt.
Dynamically init an instance with ES6 JavaScript class
The usual way to do this is to put your constructors on an object, and then look them up on that object using the generated string key:
let ctors = {
AnObject: class {
constructor(name) {
this.name = name;
}
}
};
let className = "An" + "Object";
let p2 = new ctors[className]("name2");
console.log("p2 name: " + p2.name);
Live copy on Babel's REPL
Alternately, and I'm just being complete here not recommending it, you can use eval
:
class AnObject {
constructor(name) {
this.name = name;
}
}
let className = "An" + "Object";
let p2 = new (eval(className))("name2");
console.log("p2 name: " + p2.name)
Live copy on Babel's REPL
Or a bit more verbose, but possibly clearer:
let className = "An" + "Object";
let ctor = eval(className);
let p2 = new ctor("name2");
console.log("p2 name: " + p2.name)
eval
is fine as long as you're in complete control of the strings you're evaluating. But it's usually overkill in well-structured code.
Get the class name of ES6 class instance
someClassInstance.constructor.name
is exactly the correct way to do this. Transpilers may not support this, but it is the standard way per the specification. (The name
property of functions declared via ClassDeclaration productions is set in 14.5.15, step 6.)
Related Topics
How to Find Events Bound on an Element with Jquery
How to Check If Dst (Daylight Saving Time) Is in Effect, and If So, the Offset
Truncate Number to Two Decimal Places Without Rounding
How to Get Unique Values in an Array
How to Upload a File with the Js Fetch API
Pass Props in Link React-Router
Convert JSON Array to an HTML Table in Jquery
Emberjs: How to Load Multiple Models on the Same Route
Make Axios Send Cookies in Its Requests Automatically
Constructor Function VS Factory Functions
Differencebetween a User and a Guildmember in Discord.Js
How to Parse JSON Using Node.Js
How to Cancel an Http Fetch() Request
How to Focus on a <Div> Using JavaScript Focus() Function
What's the Difference Between Window.Location and Document.Location in JavaScript