0

Take this example of an ES6 class for a website header:

// ./Header.js
export default class Header {
  constructor() {
    console.log('Header is constructing');
    this.root = document.querySelector('header');
    this.show = this.show.bind(this);
    this.hide = this.hide.bind(this);
    // Other stuff
  }

  // Other methods for account and interactive menus
  hide() {
    this.root.classList.add('hide');
  }

  show() {
    this.root.classList.add('show');
  }
}

Then take for example, other classes that would invoke methods from the header:

// ./Search.js
import 'Header';

export default class Search {
  constructor() {
    this.header = new Header();
    // Other stuff
  }

  // Other methods
  invoke() {
    this.header.hide();
  }

  cancel() {
    this.header.show();
  }
}
// ./ScrollToTop.js
import 'Header';

export default class ScrollToTop {
  constructor() {
    this.root = document.querySelector('#scrollToTop');
    this.header = new Header();
    this.onClick = this.onClick.bind(this);
    this.root.addEventListener('click', this.onClick);
    // Other stuff
  }

  // Other methods
  onClick() {
    window.scrollTo({top: 0});
    this.header.show();
  }
}

The header is constructed each time you use new Header. Given that we would like the Header to be both an object and an exportable: how would one design the code to make the Header only constructed once?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
henryaaron
  • 6,042
  • 20
  • 61
  • 80
  • Make `header` a parameter of your `Search` and `ScrollToTop` constructors. Construct the `new Header` once in the place where you construct the search and scrollToTop instances and pass it into them as an argument. – Bergi Dec 27 '22 at 18:46
  • @Barmar I don't think the OP is necessarily looking for a singleton. Dependency injection would be a much better solution to their problem. – Bergi Dec 27 '22 at 18:47
  • @Bergi OK, I've reopened, but doesn't that mean that the caller of both classes needs to know that they need a header passed to them? – Barmar Dec 27 '22 at 18:52

1 Answers1

0

By exporting the initialized header:

// header.js

export class Header {
  constructor() {
    console.log('Header is constructing');
    this.root = document.querySelector('header');
    this.show = this.show.bind(this);
    this.hide = this.hide.bind(this);
    // Other stuff
  }

  // Other methods for account and interactive menus
  hide() {
    this.root.classList.add('hide');
  }

  show() {
    this.root.classList.add('show');
  }
}

export default new Header()

You can now reuse it in other files, like this:

import header, { Header } from './header'
Robert-Jan Kuyper
  • 2,418
  • 12
  • 22