如何编译和评估对象上指定的逻辑运算符和操作数?

时间:2019-03-19 12:13:19

标签: javascript parsing ecmascript-6 boolean-logic

有没有一个编译器或一种简单的方法可以编译和评估对象上指定的逻辑运算符和操作数。这类似于mongodb $or$and运算符。例如:

return {
  $or: [
    foo: [...],
    bar: [...]
  ]
}

当编译器遇到foo时,它将使用为其提供的值调用相应的函数。 bar也是如此。然后它将logical OR两次操作的结果。我想处理$and$or运算符。我将对这样一个简单的示例进行简单的检查,但是我希望能够嵌套逻辑运算符。一个复杂的例子:

return {
  $or: [
    { 
      $and: [
        { foo: [...] }, 
        { bar: [...] }
      ] 
    }, 
    { baz: [...] }, 
    () => m < n
  ]
}

foobarbaz的简化定义:

export const evalFoo = items => {
  return items.indexOf("foo") >= 0;
};

export const evalBar = items => {
  return items.indexOf("bar") >= 0;
};

export const evalBaz = items => {
  return items.indexOf("baz") >= 0;
};

样本数据:

设置1

m = 4; n = 1; foo: ['foo', 'x']; bar: ['bar', 'y']; baz: ['baz', 'z']

RESULT = true; // because $and results to true.

设置2

m = 4; n = 1; foo: ['x']; bar: ['y']; baz: ['x']

RESULT = false; // because m > n and $and results to false.

设置3

m = 1; n = 3; foo: ['x']; bar: ['y']; baz: ['x']

RESULT = true; // because m < n.

设置4

m = 3; n = 1; foo: ['x']; bar: ['bar']; baz: ['z']

RESULT = true; // because m > n, baz() is false and x and $and is false.

1 个答案:

答案 0 :(得分:1)

您可以采用类似的方法,在$and$or或函数之间进行区分。

它的工作原理是使用带有Array#every之类的数组方法的键的对象,该方法类似于逻辑,并通过测试对象中的值,如果所有带有回调的项都返回a,则返回true truthy值。类似的方法Array#some,但回调只返回一个真实值,只需要一项。

另一个对象包含功能,并允许使用键来访问它们。

第一个参数检查参数是否为函数,如果是,则返回调用结果。

然后参数得到检查,如果falsy(如null,或者如果该值不是对象,则函数以false终止。

对于键/值对,destructuring assignment与对象的第一个条目一起发生。

如果key在运算符对象中,则该值将作为迭代value的方法并返回。

如果key在函数对象中,则以value作为参数调用该函数并返回。

最后返回false,因为没有其他检查成立,并且条件无法解决。

function evaluate(object) {
    var operators = { $or: 'some', $and: 'every' },
        fns = {
            foo: items => items.indexOf("foo") >= 0,
            bar: items => items.indexOf("bar") >= 0,
            baz: items => items.indexOf("baz") >= 0
        },
        key,
        value;

    if (typeof object === 'function') return object();
    if (!object || typeof object !== 'object') return false;

    [key, value] = Object.entries(object)[0];

    if (key in operators) return value[operators[key]](evaluate);
    if (key in fns) return fns[key](value);
    return false;
}

var m = 4,
    n = 1,
    object = {
        $or: [
            {
                $and: [
                    { foo: ['foo', 'x'] },
                    { bar: ['bar', 'y'] }
                ]
            },
            { baz: ['baz', 'z'] },
            () => m < n
        ]
    },
    result = evaluate(object);

console.log(result);