Javascript Question of the Day #21 [Talk::Overflow]

Published: (February 24, 2026 at 06:17 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

This post explains a quiz originally shared as a LinkedIn poll.

Quiz Code

function Animal(name) {
  this.name = name;
}

Animal.prototype = {
  speak() {
    return this.name + ' makes a sound';
  }
};

const dog = new Animal('Rex');

console.log(dog.speak());
console.log(dog.constructor === Animal);
console.log(dog instanceof Animal);
console.log(dog.constructor === Object);

Output

Rex makes a sound
false
true
true

Explanation

Every function in JavaScript is automatically given a prototype object that contains a single non‑enumerable property: constructor, pointing back to the function itself. When you replace the entire prototype with a new object literal (Animal.prototype = { ... }), that replacement object is just a plain Object. Its constructor property is inherited from Object.prototype and therefore points to Object, not Animal.

  • dog.speak() – The instance has no own speak method, so JavaScript looks up the prototype chain, finds speak on the replacement prototype, and calls it with this bound to dog.
  • dog.constructor === Animal – The instance has no own constructor. The lookup reaches the replacement prototype (which also lacks constructor), then Object.prototype, whose constructor is Object. Hence the comparison is false.
  • dog instanceof Animal – The instanceof operator checks whether Animal.prototype appears anywhere in dog’s internal [[Prototype]] chain. Since dog.__proto__ is exactly the replacement prototype, the result is true.
  • dog.constructor === Object – As explained, the lookup resolves to Object.prototype.constructor, so the comparison is true.

The Non‑Obvious Part

Developers often treat constructor and instanceof as two views of the same relationship, but they are not:

  • instanceof walks the live prototype chain and checks for a specific prototype object.
  • constructor is just a regular property that can be lost, overwritten, or inherited from the wrong place.

Replacing the entire prototype object severs the constructor link while leaving instanceof intact, creating an inconsistency.

Key Takeaways

  • Replacing Fn.prototype entirely destroys the constructor link. The new object literal inherits constructor from Object.prototype, which points to Object.

  • Always restore the constructor if you replace the prototype:

    Animal.prototype.constructor = Animal;
  • instanceof and constructor check different things; they should not be used interchangeably for type checking.

Best Practices

  • Augment prototypes instead of replacing them. Use:

    Animal.prototype.speak = function () {
      return this.name + ' makes a sound';
    };

    This adds methods without losing the original constructor.

  • If you must replace the prototype, explicitly set the constructor property back to the original function.

  • Prefer ES6 class syntax, which handles prototype augmentation correctly and preserves the constructor automatically.

  • Never rely on constructor for type checking in production. Use instanceof, Symbol.hasInstance, or explicit type tags instead. Treat constructor as an informational convenience, not a guarantee.

0 views
Back to Blog

Related posts

Read more »

Chat SDK adds Telegram adapter support

Telegram Adapter Support Chat SDK now supports Telegram, extending its single‑codebase approach to Slack, Discord, GitHub, and Teams, with the new Telegram ada...