在 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/