Metaclasses In JavaScript (ES6)

Introduction

 
JavaScript is an extremely powerful language. Its simple yet dynamic nature allows you to do some pretty amazing things. In this article, I'll be describing how you can generate classes dynamically, at runtime. This concept of generating a class with code is called a Metaclass.
 
 
"In object-oriented programming, a metaclass is a class whose instances are classes. "
 
Prerequisite
 
This article assumes knowledge of modern JavaScript syntax features, such as:
 
The Code
 
Our metaclass will be defined as a constructor function. This function will accept parameters corresponding to the class properties we want, and return a class that will have those properties when instantiated. The class that gets returned from the function can be instantiated like any other ES6 class.
 
For this function. we'll use the rest operator to accept an arbitrary amount of arguments.
  1. function createClass(...properties){  
  2.   // ...  
  3. }  
Next, we'll be returning a new class using an anonymous class expression. Again, we'll use the rest operator to accept an arbitrary number of arguments. 
  1. function createClass(...properties){  
  2.     return class {  
  3.         constructor(...values){  
  4.             // ...  
  5.         }  
  6.     }  
  7. }  
 Now we're getting somewhere. The only thing we need to do now, is to add our properties to the class, and assign our values to them in the constructor.
 
We can do this using a for..of  loop, utilizing destructuring to get the information we need.
  1. function createClass(...properties){  
  2.     return class {  
  3.         constructor(...values){  
  4.             for(const [index, property] of properties.entries()){  
  5.                 // ...  
  6.             }  
  7.         }  
  8.     }  
  9. }  

The Completed createClass() Function

 
Now that we have acess to the property and its corresponding index, we can now dynamically add these properties to the generated class, and assign their value
  1. function createClass(...properties){  
  2.     return class {  
  3.         constructor(...values){  
  4.             for(const [index, property] of properties.entries()){  
  5.                 this[property] = values[index];  
  6.             }  
  7.         }  
  8.     }  
  9. }  
That's all there is to it! We now have an effective metaclass constructor. This can be used to dynamically generate a class using strings for properties and values. An example use-case is generating your model classes based on a configuration file, allowing for some very high extendability.
 

Using the Metaclass

 
Here's a contrived example of creating a UserModel class dynamically using our new constructor function.
  1. const UserModel = createClass('username''passwordHash''email''age');  
Seeing how it's used makes this concept much clearer, in my opinion.
 
We can instantiate a new UserModel just like any other class:
  1. const user = new UserModel('SeanF''hash_goes_here''example@email.com', 24);  
  2. console.log(`${user.username}, age ${user.age}`);  

Conclusion

 
Just as I stated before, JavaScript is powerful. A concept like metaclass doesn't even need to be supported directly by syntax-level features, yet it's still trivial to write. 
 
I hope this information proves useful to you, or at least has prompted some inspiration for creative ways to apply JavaScript's dynamic nature in your own code!
 
Stay safe everyone!