2016-09-10 7 views
0

私は、データ・コンテキスト(オブジェクト)に関するユーザー定義の条件を格納、検索、処理する必要があり、将来のある時点でコンテキストがユーザーの基準を満たしているかどうかを判断する状況があります。Javascriptでシリアライズ可能な述語を使用するにはどうすればよいですか?

LogicJSは、私が必要とするものが少し複雑に思えますが、条件を保存して取得する必要性を明確に解決していません。

SO:How can I serialize a function in JavaScript?(tldr; function.toString()とeval())は動作するようですが、重大なセキュリティホールのようにも見えます。

これに関する一般的な解決策はありますか?

+0

どのようにユーザーが自分の条件を定義していますか?彼らはJavaScriptを書いているのですか、UIと対話していて、入力から述部を生成していますか? – vlaz

+0

一般的なチェック(オブジェクト、制約)関数を使用できませんでした。制約は、オブジェクトのプロパティと値をテストできるユーザー生成オブジェクトです。たとえば、contraints = {propertyOne:["string"、["a"、 "b"、 "orC"]]、propertyTwo:[variableType、arrayOfValues]}のようになります。 –

+0

@AlbertJamesTeddyこれは私が運転していたものです。私は、ユーザーがいくつかのUIを使って述語を生成すると想像しています。そのようにすれば、定義上、ユーザー入力(本質的には値の束として表現される)を述語に変換する手段がいくつかあります。そこから、「この関数をどのように保存するか」から「どのようにこれらの値を格納するか」という問題が変わります。同じ述語を得るために、述語生成に対して値を再生するだけです。そのことを念頭において、解決するのは簡単です。 – vlaz

答えて

1

私が使っている解決策は@vlazと@AlbertJamesTeddyです。私は既存の一般化された解決策を見つけることができませんでした。 2016年9月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

関連する問題