Javascript 用谓词列表替换条件列表(if/switch/trialoperators)的优缺点是什么?

Javascript 用谓词列表替换条件列表(if/switch/trialoperators)的优缺点是什么?,javascript,conditional,predicate,Javascript,Conditional,Predicate,最近我遇到了一个学派,主张用其他的东西(多态性、策略、访问者等)替换条件句(if/switch/trialoperators,下同) 正如我想通过尝试新方法了解的那样,我修改了一些Javascript代码,并立即发现了一个相关案例,基本上是以下ifs列表(基本上与开关/嵌套三元运算符相同): 不久之后,我想出了一个谓词列表来代替 假设checkResult总是返回一个字符串(这适用于我的特定情况),上面的ifs列表可以替换为一个谓词列表(它使用箭头函数并查找哪些是ES6+功能): (另请注意:c

最近我遇到了一个学派,主张用其他的东西(多态性、策略、访问者等)替换条件句(if/switch/trialoperators,下同)

正如我想通过尝试新方法了解的那样,我修改了一些Javascript代码,并立即发现了一个相关案例,基本上是以下ifs列表(基本上与开关/嵌套三元运算符相同):

不久之后,我想出了一个谓词列表来代替

假设checkResult总是返回一个字符串(这适用于我的特定情况),上面的ifs列表可以替换为一个谓词列表(它使用箭头函数并查找哪些是ES6+功能):

(另请注意:checkResult是否应将resultConds和defaultResult作为参数在这里应该是一个相对较小的问题,如下所示)

如果上述假设不成立,谓词列表可以改为:

var conds = [
    isCond1Met,
    isCond2Met,
    isCond3Met,
    // More predicates here...
    isCondNMet
];
var results = [
    result1,
    result2,
    result3,
    // More results here...
    resultN
];

function checkResult(input) {
    return results[conds.findIndex(cond => cond(input))] || defaultResult;
};
更大的重构可能是这样的:

var condResults = {
    cond1: result1,
    cond2: result2,
    cond3: result3,
    // More mappings here...
    condN: resultN,
};
var conds = Object.keys(condResults);

function checkResult(input) {
    return condResults[conds.find(cond => isCondMet[cond](input))] || defaultResult;
};
我想问一下用谓词列表替换条件列表的利弊(最好有相关的经验和解释,),至少在这种情况下()(例如:输入验证检查返回基于条件列表的非布尔结果)

例如,哪种方法通常会带来更好的结果:

  • 可测试性(如单元测试)
  • 可伸缩性(当条件/谓词越来越多时)
  • 可读性(对于熟悉这两种方法的人,以确保充分公平的比较)
  • 可用性/可重用性(避免/减少代码重复)
  • 灵活性(例如,当用于验证输入的内部低级逻辑发生急剧变化时,同时保持相同的外部高级行为)
  • 内存占用/时间性能(特定于Javascript)
此外,如果您认为谓词列表方法可以改进,请随意演示改进方法的优缺点


编辑:正如@Bergi提到的Javascript对象是无序的,ES6+映射可能是更好的选择:)

一般来说,将业务逻辑(如这些谓词)放在单独的对象中总是可以提高可测试性、可伸缩性、可读性、可维护性和可重用性。这来自于OOP设计固有的模块化,并允许您将这些谓词保存在中央存储中,并在其上应用您想要的任何业务过程,保持独立于代码库。本质上,您将这些条件视为数据。您甚至可以动态地选择它们,根据自己的喜好进行转换,并在抽象层上使用它们

当您需要使用泛型方法来替换简单的a-short条件时,可读性可能会受到影响,但是如果您有许多谓词,那么可读性会很好

添加/更改/删除谓词的灵活性提高了很多,但是选择不同体系结构(如何应用哪种谓词)的灵活性将恶化-您不能只在一个小位置更改代码,您需要接触使用谓词的每个位置

内存和性能占用也会更大,但还不够重要


关于可伸缩性,只有当您选择一个好的体系结构时,它才起作用。需要以线性方式应用的规则列表在一定规模下可能不再适用。

一般来说,将业务逻辑(如这些谓词)放在单独的对象中总是可以提高可测试性、可伸缩性、可读性、可维护性和可重用性。这来自于OOP设计固有的模块化,并允许您将这些谓词保存在中央存储中,并在其上应用您想要的任何业务过程,保持独立于代码库。本质上,您将这些条件视为数据。您甚至可以动态地选择它们,根据自己的喜好进行转换,并在抽象层上使用它们

当您需要使用泛型方法来替换简单的a-short条件时,可读性可能会受到影响,但是如果您有许多谓词,那么可读性会很好

添加/更改/删除谓词的灵活性提高了很多,但是选择不同体系结构(如何应用哪种谓词)的灵活性将恶化-您不能只在一个小位置更改代码,您需要接触使用谓词的每个位置

内存和性能占用也会更大,但还不够重要


关于可伸缩性,只有当您选择一个好的体系结构时,它才起作用。需要以线性方式应用的规则列表在一定规模下可能不再适用。

我对此非常在行,关于可读性和实用性,我更喜欢后者,但这是个人偏好,我通常很落后,所以你不应该听我的。
条件方法更易于移植,我的意思是很容易移植到非面向对象语言。但这可能永远不会发生,即使这样,做这类事情的人可能有工具和经验,所以这不应该成为一个问题。关于性能,我怀疑会有任何显著差异,第一种看起来像分支,第二种看起来像随机访问。

但正如我所说的,你不应该听我的,因为我只是在猜测,我在这方面非常在行,关于可读性和实用性,我更喜欢后者,但这是个人偏好,我通常很落后,所以你不应该听我的。
条件方法更易于移植,我的意思是很容易移植到非面向对象语言。但这可能永远不会发生,而且
var conds = [
    isCond1Met,
    isCond2Met,
    isCond3Met,
    // More predicates here...
    isCondNMet
];
var results = [
    result1,
    result2,
    result3,
    // More results here...
    resultN
];

function checkResult(input) {
    return results[conds.findIndex(cond => cond(input))] || defaultResult;
};
var condResults = {
    cond1: result1,
    cond2: result2,
    cond3: result3,
    // More mappings here...
    condN: resultN,
};
var conds = Object.keys(condResults);

function checkResult(input) {
    return condResults[conds.find(cond => isCondMet[cond](input))] || defaultResult;
};