没有 OOP 类的 Javascript 多态性

标签 javascript functional-programming

在 JS 或 OOP 语言中,多态性是通过创建不同的类型来创建的。

例如:

class Field {...}

class DropdownField extends Field {
  getValue() { 
     //implementation ....
  }
}

假设我有一个带有一些方法的库 forms.js:

class Forms {
    getFieldsValues() {
      let values = [];
      for (let f of this.fields) {
          values.push(f.getValue());
      }
      return values;
    }
}

这会获取所有字段值。请注意,库不关心它是什么字段。

通过这种方式,开发人员 A 创建了库,开发人员 B 可以创建新字段:AutocompleterField。

他可以在不更改库代码(Forms.js)的情况下在AutocompleterField中添加方法。

如果我在JS中使用函数式编程方法,我该如何实现?

如果我在对象中没有方法,我可以使用 case 语句,但这违反了原则。类似这样:

if (field.type == 'DropdownField')...
else if (field.type == 'Autocompleter')..

如果开发人员 B 添加新类型,他应该更改库代码。

那么有什么好的方法可以在不使用面向对象编程的情况下解决javascript中的问题。

我知道 Js 既不完全是 OOP 也不完全是 FP,但无论如何。

谢谢

最佳答案

JavaScript 是一种多用途语言,您当然可以用不同的方式解决它。当切换到函数式编程时,答案非常简单:使用函数!您的示例的问题在于:它是如此精简,您只需 3 行就可以完成与它完全相同的操作:

// getValue :: DOMNode -> String
const getValue = field => field.value;

// readForm :: Array DOMNode -> Array String
const readForm = formFields => formFields.map(getValue);

readForm(Array.from(document.querySelectorAll('input, textarea, select')));
// -> ['Value1', 'Value2', ... 'ValueN']

关键是:Field::getValue() 是如何实现的,它返回 什么?或者更准确地说:DropdownField::getValue()AutocompleteField::getValue() 有何不同,例如 NumberField::getValue() ?他们都只返回值(value)吗?他们返回一对名称和值吗?他们甚至需要与众不同吗?

问题是,您的 Field 类和它们的继承类是因为它们的 getValue() 方法的工作方式不同,还是因为其他功能而不同他们有?例如,文本字段的“自动完成”功能不(或不应)与从中获取值的方式相关联。

如果你真的需要以不同的方式读取值,你可以实现一个函数,它接受 {fieldtype: readerFunction} 对的 map/dictionary/object/POJO:

/* Library code */

// getTextInputValue :: DOMNode -> String
const getTextInputValue = field => field.value;

// getDropdownValue :: DOMNode -> String
const getDropdownValue = field => field.options[field.selectedIndex].value;

// getTextareaValue :: DOMNode -> String
const getTextareaValue = field => field.textContent;

// readFieldsBy :: {String :: (a -> String)} -> DOMNode -> Array String
readFieldsBy = kv => form => Object.keys(kv).reduce((acc, k) => {
  return acc.concat(Array.from(form.querySelectorAll(k)).map(kv[k]));
}, []);



/* Code the library consumer writes */

const readMyForm = readFieldsBy({
  'input[type="text"]': getTextInputValue,
  'select': getDropdownValue,
  'textarea': getTextareaValue
});

readMyForm(document.querySelector('#myform'));
// -> ['Value1', 'Value2', ... 'ValueN']

注意:我有意没有在这里提到诸如 IO monad 之类的东西,因为它会使事情变得更复杂,但你可能想要查找它。

关于没有 OOP 类的 Javascript 多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53276744/

相关文章:

php - 输入类型密码值?

javascript - 无重复的笛卡尔积

javascript - 没有可用的数据,两侧中心(垂直 + 水平)与 HTML,CSS

javascript - 用空格替换破折号(连字符)

javascript - 如何使用 React 功能 Hook 在异步操作后获取更改的状态

javascript - 粗箭头与 map 的用法

javascript - 如何在javascript中检查td是否为空

performance - 编写无限列表以跳过 p 的每个因子?

functional-programming - Coq:证明n和(S n)的乘积是偶数

functional-programming - 我只是没有继续!