如何在Javascript中使用可序列化谓词?

时间:2016-09-10 18:29:19

标签: javascript serialization

我遇到需要存储,检索和处理的情况 用户定义的关于数据上下文(对象)的条件,确定 在未来的某个时刻,上下文是否符合用户的标准。

LogicJS似乎对我需要的东西有点复杂,也没有明确解决我存储和检索条件的需要。

SO?:How can I serialize a function in JavaScript?(tldr; function.toString()和eval())似乎会起作用,但它看起来也像是一个严重的安全漏洞。

是否存在一般的解决方案?

1 个答案:

答案 0 :(得分:1)

我正在使用的解决方案是@vlaz和@AlbertJamesTeddy建议的。我找不到现有的通用解决方案。

截至2016/09/12:

_.mixin({
  evaluatePredicateDescriptor: function (context, descriptor) {
    // A predicate descriptor must be an object with a valid 'op' String property, an appropriate 'arg' property value, and can optionally have a 'path' property.
    // e.g.
    // var egContext = [ [1, 2, 3], [2, 4, 6], [3, 6, 9, 12, 15] ];
    // var egDescriptor = { op: 'any', arg: { path: 'length', op: 'gt', arg: 6 } };
    // var result = _.evaluatePredicateDescriptor(egContext, egDescriptor); // false
    // egDescriptor = { op: 'any', arg: { op: 'any', arg: { op: 'equals', arg: 15 } } };
    // result = _.evaluatePredicateDescriptor(egContext, egDescriptor); // true
    if (this.descriptor === 'true' || this.descriptor === true) { return true; }
    if (this.descriptor === 'false' || this.descriptor === false) { return false; }
    if (!_.isEmpty(descriptor.path)) {
      context = _.get(context, descriptor.path)
    }
    switch (descriptor.op) {
      case 'true':
        return true;
        break;
      case 'false':
        return false;
        break;
      case 'and':
        return _.every(descriptor.arg, function (childDescriptor) {
          return _.evaluatePredicateDescriptor(context, childDescriptor);
        });
        break;
      case 'or':
        return _.some(descriptor.arg, function (childDescriptor) {
          return _.evaluatePredicateDescriptor(context, childDescriptor);
        });
      case 'not':
        return !_.evaluatePredicateDescriptor(context, descriptor.arg);
        break;
      case 'all':
        return _.every(context, function (contextArrayElement) {
          return _.evaluatePredicateDescriptor(contextArrayElement, descriptor.arg);
        });
        break;
      case 'any':
        return _.some(context, function (contextArrayElement) {
          return _.evaluatePredicateDescriptor(contextArrayElement, descriptor.arg);
        });
        break;
      case 'every':
        return _.every(context, descriptor.arg);
        break;
      case 'some':
        return _.some(context, descriptor.arg);
        break;
      case 'lt':
        return _.lt(context, descriptor.arg);
        break;
      case 'lte':
        return _.lte(context, descriptor.arg);
        break;
      case 'equals':
        return _.isEqual(context, descriptor.arg);
        break;
      case 'gte':
        return _.gte(context, descriptor.arg);
        break;
      case 'gt':
        return _.gt(context, descriptor.arg);
        break;
      case 'matches':
        return _.isMatch(context, descriptor.arg);
        break;
      case 'regex':
        var i = descriptor.arg.lastIndexOf('/');
        var pattern = descriptor.arg.substring(1, i);
        var flags = descriptor.arg.substring(i + 1);
        var regex = new RegExp(pattern, flags);
        return regex.test(context);
        break;
      default:
        console.warn('_.evaluatePredicateDescriptor() processed a descriptor without a valid operation.');
        break;
    }
    return false;
  }
});

https://github.com/stvrbbns/my-extended-lodash/blob/master/my-extended-lodash.js