使用函数调用动态填充对象值

时间:2019-09-03 22:45:59

标签: javascript object vue.js vuejs2

我正在使用包含以下帮助程序类和方法的VueJS应用程序:

class BiometricMap {
  static get(bioType) {
    if (!bioType) {
      return BiometricMap.default();
    }

    const bioTypes = {
      40: () => this.getFace(),
      41: () => this.getFace(),
      42: () => this.getFace(),
      43: () => this.getFace(),
      60: () => this.getVoice(),
      61: () => this.getVoice(),
      140: () => this.getPin(),
      141: () => this.getPin(),
      150: () => this.getPalm(),
      152: () => this.getPalm(),
    };

    return (bioTypes[bioType])();
  }

  static getFace() {
    return {
      friendly: 'Face',
      type: 'face',
      icon: 'face',
    };
  }

  static getPalm() {
    return {
      friendly: 'Palm',
      type: 'palm',
      icon: 'pan_tool',
    };
  }

  static getPin() {
    return {
      friendly: 'PIN',
      type: 'pin',
      icon: 'radio_button_checked',
    };
  }

  static getVoice() {
    return {
      friendly: 'Voice',
      type: 'voice',
      icon: 'keyboard_voice',
    };
  }

  static default() {
    return {
      friendly: '',
      type: '',
      icon: '',
    };
  }
}

export default BiometricMap;

我需要将其转换为动态的,因为bioTypes值的列表可以更改,因此我像这样修改了get()

import BiometricService from '../services/BiometricService';
...

  static async get(bioType) {
    if (!bioType) {
      return BiometricMap.default();
    }

    const bioTypes = {};
    const baseBioTypes = await BiometricService.fetchAll();

    baseBioTypes.data.forEach((type) => {
      // Yet another place we have to convert 'passphrase' to 'voice'.
      const captureType = type.captureType === 'passphrase' ? 'voice' : type.captureType;
      const methodName = `get${captureType.charAt(0).toUpperCase() + captureType.slice(1)}()`;
      bioTypes[type.bioType] = () => this[methodName];
    });

    return (bioTypes[bioType])();
  }

这似乎起作用,因为我正确地生成了methodName值并将其添加到bioTypes对象中。但是,当到达

return (bioTypes[bioType])();

它没有调用适当的方法(例如getFace()getVoice()等)。我在填充bioTypes对象的方式上需要做哪些更改,以便调用适当的方法?

1 个答案:

答案 0 :(得分:0)

此行似乎有可能是错误的:

const methodName = `get${captureType.charAt(0).toUpperCase() + captureType.slice(1)}()`;

因此,如果captureTypevoice,则methodName将为getVoice()。我认为您不希望()结尾。

然后是这个

bioTypes[type.bioType] = () => this[methodName];

如果我们将其全部写清楚,就会发现问题出在哪里:

bioTypes[type.bioType] = function () {
  // Ignoring the scoping issue for a moment...
  return this[methodName];
}

该函数将返回您的方法,而不是调用它。

您反而想要:

bioTypes[type.bioType] = () => this[methodName]();

下面是纠正错误的完整示例:

BiometricService = {
  async fetchAll () {
    return {
      data: [
        { bioType: 40, captureType: 'face' },
        { bioType: 41, captureType: 'face' },
        { bioType: 42, captureType: 'face' },
        { bioType: 43, captureType: 'face' },
        { bioType: 60, captureType: 'passphrase' },
        { bioType: 61, captureType: 'passphrase' },
        { bioType: 140, captureType: 'pin' },
        { bioType: 141, captureType: 'pin' },
        { bioType: 150, captureType: 'palm' },
        { bioType: 152, captureType: 'palm' }
      ]
    };
  }
};

class BiometricMap {
  static async get(bioType) {
    if (!bioType) {
      return BiometricMap.default();
    }

    const bioTypes = {};
    const baseBioTypes = await BiometricService.fetchAll();

    baseBioTypes.data.forEach((type) => {
      // Yet another place we have to convert 'passphrase' to 'voice'.
      const captureType = type.captureType === 'passphrase' ? 'voice' : type.captureType;
      const methodName = `get${captureType.charAt(0).toUpperCase()}${captureType.slice(1)}`;
      bioTypes[type.bioType] = () => this[methodName]();
    });

    return (bioTypes[bioType])();
  }

  static getFace() {
    return {
      friendly: 'Face',
      type: 'face',
      icon: 'face',
    };
  }

  static getPalm() {
    return {
      friendly: 'Palm',
      type: 'palm',
      icon: 'pan_tool',
    };
  }

  static getPin() {
    return {
      friendly: 'PIN',
      type: 'pin',
      icon: 'radio_button_checked',
    };
  }

  static getVoice() {
    return {
      friendly: 'Voice',
      type: 'voice',
      icon: 'keyboard_voice',
    };
  }

  static default () {
    return {
      friendly: '',
      type: '',
      icon: '',
    };
  }
}

(async () => {
  console.log('40 :', await BiometricMap.get(40));
  console.log('60 :', await BiometricMap.get(60));
  console.log('140 :', await BiometricMap.get(140));
  console.log('150 :', await BiometricMap.get(150));
})()

我要补充一点,每次加载所有bioTypes,在bioTypes中建立一个数据结构,然后调用其中一个,将所有其他都扔掉,这似乎有些奇怪。实现单个方法调用似乎正在进行很多工作。

以目前的形式,可以简化为:

static async get(bioType) {
  if (!bioType) {
    return BiometricMap.default();
  }

  const baseBioTypes = await BiometricService.fetchAll();

  for (const type of baseBioTypes.data) {
    if (type.bioType === bioType) {
      const captureType = type.captureType === 'passphrase' ? 'voice' : type.captureType
      const methodName = `get${captureType.charAt(0).toUpperCase()}${captureType.slice(1)}`
      return this[methodName]()
    }
  }

  // TODO: Handle fall-through
}

要使现有版本有意义,就需要采用某种方式保留对象bioTypes,以便多次使用该对象。即使那样,我还是更倾向于只包含从bioTypemethodName字符串的映射,而不是创建所有这些包装函数。