the object whose prototype chain is to be found.
optional configuration for slicing the full prototype chain.
the sliced prototype chain of the given object.
import { assertEquals, assertThrows } from "jsr:@std/assert"
// aliasing our functions for brevity
const
fn = prototypeChainOfObject,
eq = assertEquals
class A extends Array { }
class B extends A { }
class C extends B { }
class D extends C { }
const
a = new A(0),
b = new B(0),
c = new C(0),
d = new D(0)
eq(fn(d), [D.prototype, C.prototype, B.prototype, A.prototype, Array.prototype, Object.prototype, null])
eq(fn(b), [B.prototype, A.prototype, Array.prototype, Object.prototype, null])
// slicing the prototype chain, starting from index 2 till the end
eq(fn(d, { start: 2 }), [B.prototype, A.prototype, Array.prototype, Object.prototype, null])
// slicing using a negative index
eq(fn(d, { start: -2 }), [Object.prototype, null])
// slicing using an object
eq(fn(d, { start: B.prototype }), [B.prototype, A.prototype, Array.prototype, Object.prototype, null])
// when the slicing object is not found, the start index will be assumed to be `0` (default value)
eq(fn(d, { start: Set.prototype }), [D.prototype, C.prototype, B.prototype, A.prototype, Array.prototype, Object.prototype, null])
// slicing between the `start` index (inclusive) and the end index
eq(fn(d, { start: 2, end: 6 }), [B.prototype, A.prototype, Array.prototype, Object.prototype])
eq(fn(d, { start: 2, end: -1 }), [B.prototype, A.prototype, Array.prototype, Object.prototype])
eq(fn(d, { start: 2, end: null }), [B.prototype, A.prototype, Array.prototype, Object.prototype])
// if the end index is not found, the slicing will occur till the end
eq(fn(d, { end: Set.prototype}), [D.prototype, C.prototype, B.prototype, A.prototype, Array.prototype, Object.prototype, null])
// slicing using a `delta` argument will let you define how many elements you wish to:
// - traverse forward from the `start` index
// - traverse backwards from the `end` index
eq(fn(d, { start: 2, delta: 3 }), [B.prototype, A.prototype, Array.prototype])
eq(fn(d, { end: -2, delta: 2 }), [A.prototype, Array.prototype])
eq(fn(d, { end: null, delta: 4 }), [B.prototype, A.prototype, Array.prototype, Object.prototype])
eq(fn(d, { start: 1, delta: 1 }), fn(c, { start: 0, delta: 1 }))
eq(fn(c, { start: 1, delta: 1 }), fn(b, { start: 0, delta: 1 }))
eq(fn(b, { start: 1, delta: 1 }), fn(a, { start: 0, delta: 1 }))
eq(fn(a, { start: 1, delta: 1 }), fn([], { start: 0, delta: 1 }))
eq(fn([], { start: 1, delta: 1 }), fn({}, { start: 0, delta: 1 }))
// you may also traverse through the inheritance chain of a class, but it will be a good idea to set your `end` point to `Function.prototype`,
// since all class objects are effectively functions (i.e. their common ancestral prototype if `Function.prototype`).
eq(fn(D, { start: 0, end: Function.prototype }), [C, B, A, Array])
eq(fn(D), [C, B, A, Array, Function.prototype, Object.prototype, null])
eq(fn(class {}), [Function.prototype, Object.prototype, null])
eq(fn(class extends Object {}), [Object, Function.prototype, Object.prototype, null])
eq(fn(class extends Map {}), [Map, Function.prototype, Object.prototype, null])
// you cannot acquire the prototype chain of the `null` object
assertThrows(() => { fn(null) })
get the prototype chain of an object, with optional slicing options.