AI Entities in the Future and the Concepts of Life and Soul

In the future, or even now, these are the entities related to AI: Computer A computer is an oracle computer (knowledge) operating on input/o...

07 April, 2025

How to Fix Circular Dependencies in JavaScript

The Situation

Quite a lot related to Webpack tool which doesn't place temporary unspecified module pointers for unresolved modules, and while everything is working in browser by importing files with 'import' and 'extends' keywords, Webpack will just fail.

The scenario:
  1. Class A imports Class B
  2. Class B inherits from Class C
  3. Class C imports Class A
The circle is:
  • A --import--> B --inherit--> C --import--> A
These are what being used in static context:
  • Problem 1: Call a static method of a class
  • Problem 2: Inherit a class (with 'extends' keyword)

Draft Solution

1️⃣In order to solve problem 1, just put the calls to static methods in an 'init' method. This is easy. And don't unpack in static context, eg. don't import {module} from "./libs/lib.js";, do: 
  • const {module} = lib; where needed in a dynamic context instead.

2️⃣Problem 2 is different, it's a keyword, and it's impossible to remove or called in 'init' method. There's a way to solve this (as suggested by ChatGPT), that is inheriting it dynamically:

// Bind this somewhere global
const extend = Object.setPrototypeOf;

// Import class C as usual
import C from "./C.js";

// Comment out 'extends'
class B /*extends C*/ {
    constructor(){
        // super(); // No need to call, can't call
        extend(this, new C());
    }
    ...
}

Final Solution

Although using Object.setPrototypeOf can make the child have all the methods from parent class but it overwrites the child class methods with parent ones. This `extend_to` function solves the problem:

window.methods = function(Obj){
    var Names = [];

    for (let Name of props(Obj))
        if (Name!="constructor" && typeof Obj[Name]=="function")
            Names.push(Name);

    return Names;
};
window.extend_to = function(Childclass,Child,Pa){
    var Orig_Child_Methods = methods(Child)
    var Orig_Pa_Methods    = methods(Pa)
    
    // Set super to Pa, but this overwrites child methods
    // with Pa's methods
    Object.setPrototypeOf(Child,Pa)
    Child.super = Pa;

    // Set back the methods of child
    for (let M of Orig_Child_Methods)
        Child[M] = Childclass.prototype[M];
};

How to use:

class childclass {
    constructor(){
        extend_to(childclass, this, new parentclass());
    }
}

Now circular dependencies in all cases are solved, but be aware, is this kind of dynamic inheritance complete?.

No comments:

Post a Comment