'ReferenceError: can't access lexical declaration `Tag' before initialization

Hi I'm working on a Vanilla JS SPA project, and I wanted to implement some principles from React, but just in plain JavaScript. But there is an issue with importing classes, that I'm not sure whats going on. I've looked through some answers to similar topics, but non were helpful so far.

So there is an index.js file with Class Tag.

import { banner } from './components/banner.js';

export class Tag {
constructor(parent, child, attribute, text) {
    this.parent = parent;
    this.child = child;
    this.attribute = attribute;
    this.text = text;
    }
}

Tag.prototype.createTagElement = function() {
  let parent = this.parent;
  let child = this.child;
  let attribute = this.attribute;
  let text = this.text;

  child = document.createElement(child);
  parent.appendChild(child);
  child.innerHTML = text;

  for (let key in attribute) {
    if (attribute.hasOwnProperty(key)) {
        let value = attribute[key]; 

        child.setAttribute(key, value);
    }
  }

  return child;
}

And the banner component js file.

import { Tag } from '../index.js';

//Below from here there is only DOM structure writen in JavaScript;
// HTML DOM Site Structure based on my own custom Tag Class;
//Whole structure and code can be parted to independent components.
const body = document.querySelector("body");
const attribute = {"class": "test", "style": "background-color: red"};


//Site Banner
export const Banner = new Tag(
  body, 
  "div", 
  { "class": "banner" }, 
  "Banner"
); 
export const banner = Banner.createTagElement();

I've used almost basic Webpack configuration, with few simple plugins and loaders.

If I don't split those to the separate files, it works perfectly, but when I try to put it separate i have:

ReferenceError: can't access lexical declaration `Tag' before initialization main.4f842e.js line 469 > eval:2:95
<anonymous> webpack:///./src/index.js?:2
<anonymous> webpack:///./src/components/banner.js?:15
js http://localhost:8080/js/main.4f842e.js:457
__webpack_require__ http://localhost:8080/js/main.4f842e.js:20
<anonymous> webpack:///./src/index.js?:3
js http://localhost:8080/js/main.4f842e.js:469
__webpack_require__ http://localhost:8080/js/main.4f842e.js:20
<anonymous> webpack:///multi_(webpack)-dev-server/client?:2
0 http://localhost:8080/js/main.4f842e.js:480
__webpack_require__ http://localhost:8080/js/main.4f842e.js:20
<anonymous> http://localhost:8080/js/main.4f842e.js:84
<anonymous> http://localhost:8080/js/main.4f842e.js:87

So I'm asking for a help why it doesn't work that way? Thanks for your help in advance.



Solution 1:[1]

You have to eliminate circular (recursive) references, in which you can use an object before it has been instantiated. In other words, banner is supposed to contain an instance of Tag (referencing a value) whose class has not been defined (before initialization).

Your index.js imports banner and banner.js imports Tag. So the index.js is expecting banner to contain an instance of Tag already, before Tag is defined. banner.js is trying to import index.js, which is trying to import banner.js, which is trying to import index.js, etc.

Removing the import { Tag } from '../index.js' statement from banner.js and moving the Tag definition from index.js into banner.js should resolve the problem.

Solution 2:[2]

Don't know if this may help but I had a similar problem looping through an array while setting it while declaring the variable. Example of the mistake:

// Code that threw the error
let labels = stores.map((store) => labels.push(store.storeName));

To fix this issue I changed the code statement from the above to this

// Use this working code - stores is an array
let labels = [];
stores.map((store) => labels.push(store.storeName));

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Suncat2000
Solution 2 Caleb C. Adainoo