如何设计仅构造一次的可导出ES6 Header类?
实现Header类的单例模式(仅实例化一次)
要让Header类只被构造一次,本质是实现单例模式,下面提供两种实用方案:
方案一:直接导出实例(最简单直接)
修改Header.js,不再导出类,而是直接导出提前创建好的唯一实例:
// ./Header.js 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 } hide() { this.root.classList.add('hide'); } show() { this.root.classList.add('show'); } } // 导出唯一实例,所有导入的地方共享这一个 export default new Header();
然后修改调用方的代码,直接使用导入的实例即可(不需要再new):
修改后的Search.js
// ./Search.js import header from './Header'; export default class Search { constructor() { this.header = header; // Other stuff } invoke() { this.header.hide(); } cancel() { this.header.show(); } }
修改后的ScrollToTop.js
// ./ScrollToTop.js import header from './Header'; export default class ScrollToTop { constructor() { this.root = document.querySelector('#scrollToTop'); this.header = header; this.onClick = this.onClick.bind(this); this.root.addEventListener('click', this.onClick); // Other stuff } onClick() { window.scrollTo({top: 0}); this.header.show(); } }
这种方式的好处是彻底避免重复实例化,所有模块共享同一个实例,代码改动清晰。
方案二:类内部实现单例逻辑(兼容原有调用代码)
如果不想修改调用方的new Header()写法,可以在Header类内部添加单例判断逻辑:
// ./Header.js export default class Header { // 私有静态属性,存储唯一实例 static #instance; constructor() { // 如果已有实例,直接返回,不再执行后续构造逻辑 if (Header.#instance) { return Header.#instance; } console.log('Header is constructing'); this.root = document.querySelector('header'); this.show = this.show.bind(this); this.hide = this.hide.bind(this); // Other stuff // 保存当前实例到静态属性 Header.#instance = this; } hide() { this.root.classList.add('hide'); } show() { this.root.classList.add('show'); } }
这种方案下,调用方的代码完全不需要修改——哪怕多次执行new Header(),都会返回同一个实例,构造函数只会执行一次。
两种方案各有优劣:方案一更简洁安全,方案二兼容原有代码习惯,可根据项目需求选择。
内容的提问来源于stack exchange,提问作者henryaaron
相关产品推荐
相关产品推荐

