What is constructor.constructor()() in JavaScript?

Learn what is constructor.constructor()() in javascript? with practical examples, diagrams, and best practices. Covers javascript, node.js, angularjs development techniques with visual explanations.

Demystifying constructor.constructor()() in JavaScript

Hero image for What is 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()()

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):

  1. 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.
  2. 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.
  3. 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.