0

我得到了关于 js 扩展系统的想法。通过阅读以下代码会更容易理解我的意思

在 moduleA.js 我有 Frame 类

class Frame{  // contains frame info 

    static Predefined_Paramters_Pattern = [1,2,3,4]

    constructor(someParameters = {variable1=...,variable2=...,tag = 0}){
      //do something
      this.someParamtersPattern = someParamters
    }

    nextFrame(){
      // for example
      // when i call nextFrame it 'll construct 4 subclasses 
      // base on [this] constructor paramaters
      // constructorParmatersPattern = {variable1=...,variable2=...,tag= 1 or 2 or 3 or 4}
      // this code may looks meaningless 
      // but i just wanna make this a lot easier to be comprehended what i mean 
      // and avoid stucking into a complex business logic
      Frame.Predefined_Paramters_Pattern.forEach(e=>{
          // create sub class somehow
          let type = this.type
          this.someParamtersPattern.tag = e
          let constructorParmatersPattern = this.someParamtersPattern
          // if i use eval(`new ${type}(${constructorParmatersPattern })`)
          // the browser will throw a error looks like 'SubFrame1 is not define'
      })
      
    }
 }
export {Frame}

在 moduleB.js 我有 SubFrame1 类

import {Frame} from './moduleA.js'

class SubFrame1 extends Frame{
    constructor(somePramaters){
      //do something
      super(somePramaters)
      //do something
      this.type = 'SubFrame1'
    }

}
export {SubFrame1}

现在我想要实现的是,当我调用时new SubFrame1().nextFrame(),它会自动创建几个子帧,这些子帧类似于我创建的子帧。我可以为其构造函数的参数定义一些模式。所以无论我有多少子类,只要它们扩展了 Frame,那么它们在调用.nextFrame().

但问题是我不希望在我的原始类中有一个 SubFrame1 类或 SubFrame1,SubFrame2,...,SubFrame3 类的引用。

像这个

import {SubFrame1} from './subframe1.js'
import {SubFrame2} from './subframe2.js'
......
import {SubFrameN} from './subframen.js'

class Frame{
  ......
}

我几乎是 javascript 的新手,但在学校我被告知要编写代码,以便我可以重用它们并减少冗余代码,任何帮助或更正都会很棒

4

2 回答 2

0

编辑:Bergi 提供了一个更好的解决方案!

____________________________________________________________________

我在下面的链接中了解我如何使用 es6 Reflect API 做到这一点 创建“类”的实例 在由 soulshined 发布的JavaScript 中使用“反射”

in moduleA.js
class Frame{  // contains frame info 

    static Predefined_Paramters_Pattern = [1,2,3,4]

    constructor(someParameters = {variable1=...,variable2=...,tag = 0}){
      //do something
      this.someParamtersPattern = someParamters
    }

    nextFrame(){
      Frame.Predefined_Paramters_Pattern.forEach(e=>{
          // create sub class
          let type = this.type
          this.someParamtersPattern.tag = e
          let constructorParmatersPattern = this.someParamtersPattern
          Reflect.construct(this.type, constructorParmatersPattern )
      })
      
    }
 }
export {Frame}

和子类

import {Frame} from './moduleA.js'

class SubFrame1 extends Frame{
    constructor(somePramaters){
      //do something
      super(somePramaters)
      //do something
      this.type = SubFrame1
    }

}
export {SubFrame1}
于 2021-07-25T09:04:20.347 回答
0

所以你要new SubFrame1().nextFrame()构造一个SubFrame1实例,却要new SubFrame2().nextFrame()构造一个SubFrame2实例。没有比这更容易的了,你甚至不需要type财产!JS 原型对象(例如使用class语法构建)已经包含一个.constructor属性,该属性包含构造函数,您可以调用该属性来创建同一(子)类的新实例。

export class Frame{  // contains frame info
    constructor(someParameters) {
        // do something
        this.someProperties = someParameters;
    }

    nextFrame() {
        const type = this.constructor;
        const instance = new type(this.someProperties);
        return instance;
    }
}

现在这假设子类构造函数将使用相同的签名调用,并且始终期望该this.someProperties对象作为克隆框架的参数。要自定义这一点,子类当然可以修改this.someProperties,但是一旦签名变得太不同,子类应该更好地覆盖整个方法:

class SpecialFrame extends Frame {
    constructor(someParameters, someSpecials) {
        super(someParameters);
        this.specialProperties = someSpecials;
    }
    nextFrame() {
        return new this.constructor(this.someProperties, this.specialProperties);
    }
}

这也可以用于更复杂的初始化,而不仅仅是复制属性值,或者硬编码一些nextFrame应该始终使用的特定参数。如果nextFrame不只是克隆,则将其拆分为两个方法 -clone()创建副本并可能在子类中被覆盖,然后nextFrame调用this.clone()修改副本以成为下一帧而不是相同的帧。

于 2021-07-25T13:07:10.583 回答