Check JavaScript Prototype Ancestry

Quick Overview

Practice JavaScript prototype ancestry with primitive boxing, superclass chains, and invalid arguments in a bounded checkIfInstanceOf exercise.

Check JavaScript Prototype Ancestry

Company: Google

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Other

# Check JavaScript Prototype Ancestry Implement `checkIfInstanceOf(obj, classFunction)`, returning a Boolean that reports whether a value has a specified prototype among its strict ancestors. This is an ordinary prototype-chain exercise. Use the rules below; custom instance-check hooks do not determine the result. ### Rules - Either argument may have any ordinary JavaScript value type, including `undefined`, `null`, Boolean, number, bigint, string, symbol, object, or function. Missing arguments are `undefined`. - Return `false` if `obj` is `null` or `undefined`, or if `classFunction` is not a function. - For a function argument, read `classFunction.prototype` using normal property lookup. If that value is `null` or is neither an object nor a function, return `false`. A bound function without a usable `.prototype` therefore returns `false`; do not substitute the bound target's prototype. - Otherwise, use the object itself for an object or function value, and its standard boxed object for a primitive. Return `true` exactly when `classFunction.prototype` occurs among that object's strict prototype ancestors. The starting object is not its own ancestor. Return `false` if the chain ends without a match. - Ignore `Symbol.hasInstance` hooks. Do not invoke a constructor or an instance method to determine the answer. ### Constraints and Clarifications Assume conventional, unmodified JavaScript built-ins and ordinary objects/functions with finite, acyclic prototype chains. The `.prototype` lookup and each prototype lookup terminate, do not throw, and remain stable throughout the call. Proxies, exotic objects, accessor-driven prototype lookup, and lookup that mutates, throws, or does not terminate are outside this bounded exercise. There is no fixed numeric limit on chain depth. The function name is retained, but the result is defined by prototype identity. Copying a method or changing a `constructor` property does not establish ancestry. The function argument need not support `new`: what matters is whether it is a function with a usable `.prototype`. ### Examples ```javascript checkIfInstanceOf(new Date(), Date); // true class Animal {} class Dog extends Animal {} checkIfInstanceOf(new Dog(), Animal); // true checkIfInstanceOf(Date, Date); // false checkIfInstanceOf(5, Number); // true ``` A date object has `Date.prototype` in its chain, and a dog object has `Animal.prototype` farther up its chain. The `Date` function itself does not have `Date.prototype` as an ancestor. Boxing `5` gives an object whose chain contains `Number.prototype`. Additional cases under this exercise's rules: ```javascript checkIfInstanceOf(undefined, Number); // false checkIfInstanceOf(5, undefined); // false checkIfInstanceOf(null, Object); // false checkIfInstanceOf({}, {}); // false checkIfInstanceOf(Object.create(null), Object); // false checkIfInstanceOf(Number.prototype, Number); // false checkIfInstanceOf(true, Boolean); // true checkIfInstanceOf(1n, BigInt); // true checkIfInstanceOf(Symbol("x"), Symbol); // true checkIfInstanceOf({}, () => {}); // false ``` ```hint Identify the relationship An object's own properties can resemble another object's properties without giving the two objects the same ancestors. ``` ### What a Strong Answer Covers - The return values for nullish values, nonfunction class arguments, and functions without a usable prototype. - Primitive boxing and strict prototype identity, including why the starting object does not count as an ancestor. - Superclass membership and cases where a `constructor` property, method names, or instance-check hooks disagree with actual prototype ancestry. - Time and auxiliary-space costs in terms of the prototype-chain length. ### Follow-up Questions - Why can copying a method from `Animal.prototype` onto an unrelated object leave the result `false`? - Why does `checkIfInstanceOf(5, Number)` differ from `5 instanceof Number`, and why would using `instanceof` also conflict with the hook rule?

Overview: Practice JavaScript prototype ancestry with primitive boxing, superclass chains, and invalid arguments in a bounded checkIfInstanceOf exercise.

Google logo
Google
mediumSoftware EngineerOtherCoding & Algorithms
0
0

Check JavaScript Prototype Ancestry

Implement checkIfInstanceOf(obj, classFunction), returning a Boolean that reports whether a value has a specified prototype among its strict ancestors.

This is an ordinary prototype-chain exercise. Use the rules below; custom instance-check hooks do not determine the result.

Rules

  • Either argument may have any ordinary JavaScript value type, including undefined , null , Boolean, number, bigint, string, symbol, object, or function. Missing arguments are undefined .
  • Return false if obj is null or undefined , or if classFunction is not a function.
  • For a function argument, read classFunction.prototype using normal property lookup. If that value is null or is neither an object nor a function, return false . A bound function without a usable .prototype therefore returns false ; do not substitute the bound target's prototype.
  • Otherwise, use the object itself for an object or function value, and its standard boxed object for a primitive. Return true exactly when classFunction.prototype occurs among that object's strict prototype ancestors. The starting object is not its own ancestor. Return false if the chain ends without a match.
  • Ignore Symbol.hasInstance hooks. Do not invoke a constructor or an instance method to determine the answer.

Constraints and Clarifications

Assume conventional, unmodified JavaScript built-ins and ordinary objects/functions with finite, acyclic prototype chains. The .prototype lookup and each prototype lookup terminate, do not throw, and remain stable throughout the call. Proxies, exotic objects, accessor-driven prototype lookup, and lookup that mutates, throws, or does not terminate are outside this bounded exercise. There is no fixed numeric limit on chain depth.

The function name is retained, but the result is defined by prototype identity. Copying a method or changing a constructor property does not establish ancestry. The function argument need not support new: what matters is whether it is a function with a usable .prototype.

Examples

checkIfInstanceOf(new Date(), Date); // true

class Animal {}
class Dog extends Animal {}
checkIfInstanceOf(new Dog(), Animal); // true

checkIfInstanceOf(Date, Date); // false
checkIfInstanceOf(5, Number);  // true

A date object has Date.prototype in its chain, and a dog object has Animal.prototype farther up its chain. The Date function itself does not have Date.prototype as an ancestor. Boxing 5 gives an object whose chain contains Number.prototype.

Additional cases under this exercise's rules:

checkIfInstanceOf(undefined, Number);       // false
checkIfInstanceOf(5, undefined);            // false
checkIfInstanceOf(null, Object);            // false
checkIfInstanceOf({}, {});                  // false
checkIfInstanceOf(Object.create(null), Object); // false
checkIfInstanceOf(Number.prototype, Number);   // false
checkIfInstanceOf(true, Boolean);           // true
checkIfInstanceOf(1n, BigInt);               // true
checkIfInstanceOf(Symbol("x"), Symbol);     // true
checkIfInstanceOf({}, () => {});            // false

What a Strong Answer Covers Guidance

  • The return values for nullish values, nonfunction class arguments, and functions without a usable prototype.
  • Primitive boxing and strict prototype identity, including why the starting object does not count as an ancestor.
  • Superclass membership and cases where a constructor property, method names, or instance-check hooks disagree with actual prototype ancestry.
  • Time and auxiliary-space costs in terms of the prototype-chain length.

Follow-up Questions Guidance

  • Why can copying a method from Animal.prototype onto an unrelated object leave the result false ?
  • Why does checkIfInstanceOf(5, Number) differ from 5 instanceof Number , and why would using instanceof also conflict with the hook rule?