5

I searched the web for some way to create instance of "Class" in "reflection" using javaScript but I found nothing.

generally i'm trying to do someting like java code.

Object o = Class.forename("MyClassName");

but in javaScript, in such way that I'll get the instance of class when I have only the name of the class, any idea?

Thankes.

Sarfraz
  • 377,238
  • 77
  • 533
  • 578
Asaf Maimon
  • 71
  • 3
  • 9

4 Answers4

6

JavaScript doesn't have classes. But if by "class" you mean you have a constructor function:

function MyClassName() {
   // do constructor things here
}

But the name of that function is in a variable:

var someclass = "MyClassName";

Then you can instantiate an instance like this:

var obj = new window[someclass]();

The above only works if MyClassName is in the global scope.

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
0

This is working for me:

var obj = eval("new  " + className + "()");
JavaSheriff
  • 7,074
  • 20
  • 89
  • 159
0

Now that JavaScript has classes thought I would offer an updated solution.

ES6 introduced an API that makes this extremely trivial but supports all new things JavaScript (modules for example, which weren't addressed in other answers, and doesn't worry about 'window' scope as mentioned in other comments). The Reflect API is well supported across browsers and all the methods are static and aren't limited to just classes, it works with objects in general.

The Reflect API even has convenience methods that are helpful beyond 'reflection-like' implementation. For example, you can quickly determine if an object has a key with:

console.log(Reflect.has(target, <key>))

Which can be considered an alternate of:

console.log(obj[<key>] !== undefined)

To instantiate a new instance of a class via javascript reflection you can call the Reflect.construct(<target>, arugmentsList) method:

animal.js

export default class Animal {

   constructor(type) {
      this.type = type;
   }

   get canSwim() {
      return ['amphibians', 'fish'].includes(this.type);
   }

}

main.js

import Animal from "./animal.js"

const instance = Reflect.construct(Animal, ['bird']);
console.log(Reflect.get(instance, 'canSwim')) //returns false

Just for brevity, you can still use mutators and accessors per normal, I simply used the Reflection.get() method for this example to demonstrate it exists, but the following is synonymous:

const instance = Reflect.construct(Animal, ['bird']);
console.log(instance.canSwim) //returns false

Of course, this works without modules, this example just demonstrates it with modules.

Reference:

soulshined
  • 9,612
  • 5
  • 44
  • 79
  • You should use the `Reflect` object only for implementing proxy traps. To access properties, use `instance.canSwim`, to check for properties, use `Object.hasOwn(object, 'key')` or `'key' in obj`, and to construct instances, use `new Animal('bird')`. – Bergi Jul 25 '21 at 10:27
  • Sure @Bergi . Like I said, it was a crude example just to demonstrate what methods it has. I agree, if you know the concrete class obviously call it directly but if you are using a factory class or some sort of utility class where the class is given as an argument and you don’t know the concrete class this is good alternative – soulshined Jul 25 '21 at 14:51
  • No! `new` works with arbitrary/dynamic classes just as well: `function construct(C) { return new C; }` – Bergi Jul 25 '21 at 15:28
  • @Bergi I’m not trying to be difficult but I truly don’t understand your point. Yes, if you know the concrete class obviously call it per normal conventions. No one is googling “how to instantiate a known concrete class with reflection” … especially via JavaScript. There are circumstances where you don’t know the concrete class and need to instantiate it. Clearly there is a need for it or else the entire Reflect API wouldn’t even exist. I just used my examples for readability but I didn’t think I would need to disclaim that on a question about meta programming strategies like reflection – soulshined Jul 25 '21 at 15:34
  • You can easily construct unknown classes with `new`, and you always could. The `Reflect` object exists as a counterpart to `Proxy`, it is not needed for instantiation and does not increase readability. The phrase "*Using reflection*" is a red hering, JS had such metaprogramming capabilities since its beginning and does not require usage of the `Reflect` object. – Bergi Jul 25 '21 at 15:52
  • @Bergi i know it doesn't increase readability man. This is frustrating, you're twisting my words. I said my examples are the way they are for readability. i never implied that Reflect API encourages or is going to make your code readable. I'm aware of the new keyword. Maybe it would help if you create an answer or code snippet with an alternative or something to visualize your intention? Something that doesn't rely on `eval` an works regardless of scope and with modules? – soulshined Jul 25 '21 at 16:06
  • 1
    Accessing a class by name from the current scope is a different issue, that's what `eval` and `window[name]` get at. This is nothing that `Reflect` helps with anyway ("*[The Reflect API] supports all new things JavaScript (modules for example …)*" is flat out wrong, `Reflect` has nothing to do with modules). But once you have a reference to the class, you can replace any `Reflect.construct(, arugmentsList)` call with `new (...arugmentsList)` and it works exactly the same. No need for `Reflect`, you should not use it here - but your answer suggests otherwise. – Bergi Jul 25 '21 at 16:12
0

Classes in Javascript are nothing but global functions. So you should be able to do this:

var o = new window["MyClassName"];

for example:

var o = new window["Array"];

Keep in mind that this example is just an example. Arrays should be created via [] syntax.

Dennis
  • 14,210
  • 2
  • 34
  • 54