Both @trincot's and @VLAZ's answers have their pros and cons, but I think I have achieved to amalgamate them together.
The approach here would be: for each parent class (closest to furthest) of one object (doesn't matter which one), check if another object is an instance of that class; if that's true, return the class; otherwise if the list is exhausted, return null
.
Note, that getParentClassesOf
is defined as a generator to avoid creating unused values (further common classes are not needed), but it should be easy enough to implement it as a plain array-returning function if needed.
function * getParentClassesOf(object) {
let current = object;
let prototype;
while (prototype = Object.getPrototypeOf(current)) {
yield prototype.constructor; // or classes.push(prototype.constructor)
current = prototype;
}
}
function getClosestCommonAncestorClass(left, right) {
for (const parentClass of getParentClassesOf(left))
if (right instanceof parentClass)
return parentClass;
return null;
}
function * getParentClassesOf(object) {
let current = object;
let prototype;
while (prototype = Object.getPrototypeOf(current)) {
yield prototype.constructor; // or classes.push(prototype.constructor)
current = prototype;
}
}
function getClosestCommonAncestorClass(left, right) {
for (const parentClass of getParentClassesOf(left))
if (right instanceof parentClass)
return parentClass;
return null;
}
// ***
class A {}
class B extends A {}
class C extends B {}
class D extends B {}
class E extends D {}
const closestCommonAncestor = getClosestCommonAncestorClass(new C(), new E());
console.log(closestCommonAncestor.name);
console.assert(closestCommonAncestor.name === "B");
See more examples