情況描述
項目是默認使用webpack編譯採用es6模塊處理方案
出現了以下錯誤
以下是我寫的測試類
A.ts
import {B} from "./b.js";
export class A {
static getInstance() {
if (!this._instance) {
this._instance = new A();
}
return this._instance;
}
flush() {
console.log("----------------flush-------------------");
}
a() {
console.log("----------------flush-------------------");
B.getInstance().zuo();//這一行的問題
}
}
B.ts
import {A} from "./a.js";
export class B extends A {
static getInstance() {
if (!this._instance) {
this._instance = new B();
}
return this._instance;
}
zuo() {
console.log("-----------13 zuo-----------------------");
A.getInstance().flush();
}
}
使用
import {A} from './js/a.js';
(new A()).flush();
原因分析
//省略部分代碼
...([function (e, t, n) {
"use strict";
n.r(t);
class o extends r {//r在下面才定義
static getInstance() {
return this._instance || (this._instance = new o), this._instance
}
zuo() {
console.log("-----------13 zuo-----------------------"), r.getInstance().flush()
}
}
class r {
static getInstance() {
return this._instance || (this._instance = new r), this._instance
}
flush() {
console.log("----------------flush-------------------")
}
a() {
console.log("----------------flush-------------------"), o.getInstance().zuo()
}
}(new r).flush()
}]);
看webpack輸出來的js代碼,就可以看出問題,
A和B循環引用,最大的錯誤是父類A使用了子類B,導致webpack把代碼編譯成JavaScript代碼時,把B誤認爲是應該先定義,結果在A還沒有初始化是就在extends後要使用它,纔會導致報錯。
模塊循環引用,在項目越做越大,人員越來越複雜的情況下是不可避免的,其實不帶繼承關係,這樣的循環引用是不會問題的。
解決方案
將原來直接調用單例改爲屬性賦值方式,如下:
private b:B;
a(){
this.b&&this.b.zuo();
}