Javascript ES6模块与继承

Javascript ES6模块与继承,javascript,inheritance,ecmascript-6,Javascript,Inheritance,Ecmascript 6,我有以下JavaScript文件: src/js/classes/Lexus.js: import {Car} from 'src/js/classes/Car'; export class Lexus extends Car { constructor() { super("Lexus"); } } import {Car} from 'src/js/classes/Car'; export class Mercedes extends Car { construct

我有以下JavaScript文件:

src/js/classes/Lexus.js:

import {Car} from 'src/js/classes/Car';

export class Lexus extends Car {
  constructor() {
    super("Lexus");
  }
}
import {Car} from 'src/js/classes/Car';

export class Mercedes extends Car {
  constructor() {
    super("Mercedes");
  }
}
import {Lexus} from 'src/js/classes/Lexus'; //either of those imports works, but not both!
import {Mercedes} from 'src/js/classes/Mercedes'; //either of those imports works, but not both!

export class Car {
  constructor(make) {
    this.make = make;
  }

  static factory(msg) {
    switch(msg) {
      case "Lexus":
        return new Lexus();
      case "Mercedes":
        return new Mercedes();
    }
  }
}
import {Lexus} from 'src/js/classes/Lexus';
import {Mercedes} from 'src/js/classes/Mercedes';
import {Car} from 'src/js/classes/Car';

var car = Car.factory("Lexus");
console.log(car);
src/js/classes/Mercedes.js:

import {Car} from 'src/js/classes/Car';

export class Lexus extends Car {
  constructor() {
    super("Lexus");
  }
}
import {Car} from 'src/js/classes/Car';

export class Mercedes extends Car {
  constructor() {
    super("Mercedes");
  }
}
import {Lexus} from 'src/js/classes/Lexus'; //either of those imports works, but not both!
import {Mercedes} from 'src/js/classes/Mercedes'; //either of those imports works, but not both!

export class Car {
  constructor(make) {
    this.make = make;
  }

  static factory(msg) {
    switch(msg) {
      case "Lexus":
        return new Lexus();
      case "Mercedes":
        return new Mercedes();
    }
  }
}
import {Lexus} from 'src/js/classes/Lexus';
import {Mercedes} from 'src/js/classes/Mercedes';
import {Car} from 'src/js/classes/Car';

var car = Car.factory("Lexus");
console.log(car);
src/js/classes/Car.js:

import {Car} from 'src/js/classes/Car';

export class Lexus extends Car {
  constructor() {
    super("Lexus");
  }
}
import {Car} from 'src/js/classes/Car';

export class Mercedes extends Car {
  constructor() {
    super("Mercedes");
  }
}
import {Lexus} from 'src/js/classes/Lexus'; //either of those imports works, but not both!
import {Mercedes} from 'src/js/classes/Mercedes'; //either of those imports works, but not both!

export class Car {
  constructor(make) {
    this.make = make;
  }

  static factory(msg) {
    switch(msg) {
      case "Lexus":
        return new Lexus();
      case "Mercedes":
        return new Mercedes();
    }
  }
}
import {Lexus} from 'src/js/classes/Lexus';
import {Mercedes} from 'src/js/classes/Mercedes';
import {Car} from 'src/js/classes/Car';

var car = Car.factory("Lexus");
console.log(car);
和app.js:

import {Car} from 'src/js/classes/Car';

export class Lexus extends Car {
  constructor() {
    super("Lexus");
  }
}
import {Car} from 'src/js/classes/Car';

export class Mercedes extends Car {
  constructor() {
    super("Mercedes");
  }
}
import {Lexus} from 'src/js/classes/Lexus'; //either of those imports works, but not both!
import {Mercedes} from 'src/js/classes/Mercedes'; //either of those imports works, but not both!

export class Car {
  constructor(make) {
    this.make = make;
  }

  static factory(msg) {
    switch(msg) {
      case "Lexus":
        return new Lexus();
      case "Mercedes":
        return new Mercedes();
    }
  }
}
import {Lexus} from 'src/js/classes/Lexus';
import {Mercedes} from 'src/js/classes/Mercedes';
import {Car} from 'src/js/classes/Car';

var car = Car.factory("Lexus");
console.log(car);
有趣的是,如果我将
雷克萨斯
或梅赛德斯导入汽车类,并调用app.js中的工厂方法,那么一切正常;但是,如果我将雷克萨斯和
梅赛德斯
导入到汽车类,我会得到一个错误:

超级表达式必须为null或函数,而不是未定义的

我错过了什么?

通常,您不希望有这样的循环依赖项。 循环依赖在最好的时候,打破一切,不编译(或传输)。 循环依赖在最糟糕的时候,会导致合并和版本控制冲突,会导致代码很难识别,看起来它们工作得很好,直到它们停止,一些可怕的状态假设导致了一些可怕的错误

您的解决方案(如果您死盯着这种形式的继承)是将
Car
提取到它自己的文件/类中,该文件/类可以单独导入,并将工厂与类分开

这在英语中是完全有意义的。
汽车不制造雷克萨斯(Lexi?)

另外,如果你想保留这个(不是一个好主意),那么你应该有一个注册方法,而不是一个硬编码的解决方案,你可以注册“雷克萨斯”和功能,使一个新的雷克萨斯

import Car from "./car";
class Lexus extends Car {
  constructor () {
    super("Lexus");
  }
  // starting to look like a bad idea
  static make () {
    return Car.make("Lexus");
  }
  // starting to look worse
  static register () {
    /* this register method does nothing, so that Lexus can't make other cars... */
  }
}

Car.register("Lexus", () => new Lexus());

export default Lexus;
情况变得更糟,但这已经相当糟糕了

如果您选择另一条路线:

// carfactory.js

const carTypes = new Map();
class CarFactory {
  static register (name, implementation) {
    carTypes.set(name, implementation);
    return CarFactory;
  }
  static make (name) {
    const makeCar = carTypes.get(name);
    return makeCar();
  }

  register (name, implementation) {
    CarFactory.register(name, implementation);
    return this;
  }
  make (name) { return CarFactory.make(name); }
}

export default CarFactory;


// index.js
import Car from "./classes/car";
import Lexus from "./classes/lexus";

import CarFactory from "./factories/car";

CarFactory
  .register("Lexus", () => new Lexus())
  .register("Bentley", () => new Bentley());

init( CarFactory );

function init (Car) {
  const lexus = Car.make("Lexus");
}

现在,没有任何课程需要知道他们不应该知道的事情。

我不确定你是否需要在app.js中导入雷克萨斯和梅赛德斯,因为它们不是在那里构造的。你确定错误不是基于Car,并且你的特定类是循环的,相互依赖的吗?如果你在每个新语句之后在cases中加一个中断,会发生什么?编辑:nvm您正在返回,因此开关不在范围内srySterling Archer,我确实需要将Lexus和/或Mercedes导入app.js,以便从工厂方法实例化。@b注意,如果基于Car的错误和使类彼此循环依赖,它如何解释这两种导入的工作原理,但不是两者都有?如果我走“另一条路线”,我的Car类应该是什么样子?@user3715778
class Car{constructor(make){this.make=make;}}
和Car.make()方法来自何处?没有
Car.make
仔细查看
init
的内部,以及调用时传递到
init
的内容。工厂的意义在于,常规代码不必知道或关心它是汽车工厂还是汽车。它被赋予了一种东西。它使用这个东西,并得到它所期望的,所以它很高兴。
map.set(名称、实现)寄存器方法内部,应该是
carTypes.set(名称、实现)而不是?