What is constructor.constructor()() in JavaScript?
Categories:
Demystifying constructor.constructor()() in JavaScript

Explore the intriguing and often misunderstood constructor.constructor()
pattern in JavaScript, understanding its mechanics, use cases, and potential pitfalls.
In JavaScript, the constructor
property is a fundamental aspect of object-oriented programming, linking an instance back to the function that created it. However, a less common and often confusing pattern involves accessing constructor.constructor()()
. This article delves into what this peculiar syntax means, how it works under the hood, and when you might encounter or even intentionally use it.
Understanding the constructor
Property
Before we tackle constructor.constructor()()
, let's recap the basic constructor
property. Every JavaScript object inherits a constructor
property from its prototype chain. This property points to the constructor function that was used to create the object. For instance, an object created with new MyClass()
will have its constructor
property pointing to MyClass
.
function Person(name) {
this.name = name;
}
const john = new Person('John Doe');
console.log(john.constructor); // Output: [Function: Person]
console.log(john.constructor === Person); // Output: true
const arr = [];
console.log(arr.constructor); // Output: [Function: Array]
console.log(arr.constructor === Array); // Output: true
Basic usage of the constructor
property
Deconstructing constructor.constructor()
Now, let's break down constructor.constructor()
. When you access john.constructor
, you get the Person
function. Functions in JavaScript are also objects, and like all objects, they have their own constructor
property. What is the constructor of a function? It's the built-in Function
constructor itself.
So, john.constructor.constructor
evaluates to the Function
constructor. This is true for any function, whether it's a user-defined function, a built-in function like Array
, or even the Object
constructor.
function MyFunction() {}
console.log(MyFunction.constructor); // Output: [Function: Function]
console.log(MyFunction.constructor === Function); // Output: true
const obj = {};
console.log(obj.constructor); // Output: [Function: Object]
console.log(obj.constructor.constructor); // Output: [Function: Function]
console.log(obj.constructor.constructor === Function); // Output: true
The constructor
of a function is Function
flowchart TD A["Object Instance (e.g., `john`)"] --> B["john.constructor (e.g., `Person` function)"] B --> C["Person.constructor (e.g., `Function` constructor)"] C --> D["Function.constructor (e.g., `Function` constructor)"] style A fill:#f9f,stroke:#333,stroke-width:2px style B fill:#bbf,stroke:#333,stroke-width:2px style C fill:#bfb,stroke:#333,stroke-width:2px style D fill:#bfb,stroke:#333,stroke-width:2px
Flow of constructor
property access
The Double Invocation: constructor.constructor()()
The final piece of the puzzle is the double invocation ()()
. Since constructor.constructor
resolves to the Function
constructor, constructor.constructor()
is equivalent to Function()
. When Function()
is called without new
, it behaves like eval()
and executes a string as JavaScript code in the global scope. If no arguments are provided, it essentially creates an empty anonymous function.
The second ()
then attempts to invoke the result of the first Function()
call. If the first call created an empty function, the second ()
would simply execute that empty function, returning undefined
.
However, if you pass a string to the first Function()
call, it will create a new function from that string. The second ()
would then invoke this newly created function.
const myObject = {};
// myObject.constructor is Object
// myObject.constructor.constructor is Function
// This creates a new anonymous function: function() { return 'Hello'; }
const dynamicFunction = myObject.constructor.constructor('return "Hello";');
console.log(dynamicFunction()); // Output: "Hello"
// If no arguments are passed, it creates an empty function
const emptyFunction = myObject.constructor.constructor();
console.log(emptyFunction()); // Output: undefined
// The full `constructor.constructor()()` pattern
// This creates an empty function, then immediately calls it.
const result = myObject.constructor.constructor()();
console.log(result); // Output: undefined
Demonstrating constructor.constructor()
and constructor.constructor()()
Function()
(or constructor.constructor()
) with string arguments is akin to eval()
and poses significant security risks. It allows arbitrary code execution and should be avoided in most applications, especially with untrusted input.Practical (and Impractical) Use Cases
While constructor.constructor()()
is rarely used in well-structured applications, understanding it sheds light on JavaScript's reflective capabilities. Its primary (and often dangerous) use case is dynamic code generation.
Potential Use Cases (mostly theoretical or for specific scenarios):
- Dynamic Function Creation: Creating functions from strings at runtime, similar to
eval()
. This is sometimes seen in templating engines or sandboxing environments, though safer alternatives exist. - Obfuscation/Malware: Due to its
eval
-like behavior and ability to bypass some static analysis, it has been historically used in obfuscated code or malicious scripts to execute arbitrary payloads. - Polyfills/Shims (Rare): In very specific edge cases, it might be used to dynamically create a function if a standard method is missing, though direct
new Function()
is clearer.
For most modern JavaScript development, direct use of Function
constructor or eval()
is discouraged due to security and performance implications. Arrow functions, regular function declarations, and module patterns offer safer and more readable alternatives for dynamic behavior.
constructor
property access for type checking or introspection, but the constructor.constructor()()
pattern is generally not part of typical AngularJS development practices.