Classes As Functions And Functions As Objects
#absurd-abstractions
08-04-2025
Javascript is already quite weird. This does not come as a surprise to nobody.
But I want to focus my article today on a metainteresting fact I have been pondering when dealing with ES6.
Functions in javascript are implemented as objects. In fact everything in Javascript is an object. So is it object-oriented? No, not really. It is a prototype-based language. This means other than in traditional oo objects are not defined by classes, but instead there is the common anchestor, the "Adam and Eve" of objects that define their features.
Function as objects give some benefits such as light-weight reflection, being able to inspect the function definition as string, or it's name at runtime.
Since objects are not nominally defined as a class in Javascript, a common pattern before ES6 was a factory function, in which we used the object as a closure to contain both internal state and function operating on the internal state with this
. The constructor would then be an internal function inside the object defining the members and returning itself.
The entire object definition is encapsulated inside the main factory function.
In ES6 a ton of new features have been introduced that made the language syntactically more clear, giving us lambda
as =>
to define anonymous expressions (for the functional style) and Class
to better fit into the object-oriented style.
Or so it seems.
See, in reality class is just a syntactical form to express the usual factory function pattern.
Instead of defining everything inside your function closure. You have clear syntactical components. Like a mandatory constructor
method, the class Name, optional base classes you extend, and your typical class methods. But when you generate an object from the class with new
, what happens is, that an object is "printed" into it's shape defined by the class with the internal values from the constructor, and as member all the methods as functions.
In fact methods in objects are just normal functions with a binding to this
as the object. I found this out during an electron implementation in which my IPC stripped my object of all it's methods.
This on the other Hand also allows you to do weird things, like taking an arbitrary function, binding it to an object, giving this
a new referent and essentially instilling the object with a new method. This allows to store methods, as simple function values and can then be reapplied to their objects as methods at runtime.
Ok, that is nice. But let us take a step back. Functions are objects. They are usually produced by functions. Objects contain other functions as methods, by binding the function context to this
. Classes are a syntactical replacement to write factory functions.
Therefore classes that are functions, that are objects, bind functions that are objects to objects, and produce more objects. Now let that melt inside your brain!
Takeaway
Functions as objects is a powerful mechanism, to be able to access function meta-data at runtime. Classes in ES6 however can be misleading. Only when having to deal with narrow use-cases it comes apparent that classes are just syntactically more elegant factory functions.
Good Example of How the semantics on the syntactical level don't reflect the semantics of the programming language implementation.