Create Object from Class Name in Javasscript Ecmascript 6

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



Leave a reply



Submit