我有一个函数,允许根据环境评估字符串
function filt(M, filterString, cb){
var res
try{
res = eval(filterString)
} catch(me){
// If in doubt permit
res = true
}
cb(res)
}
问题是,我希望这个过滤器是乐观的。你可以在catch
中看到乐观情绪,如果出现任何问题,就会将响应设置为true。
如果我运行filt({ age : 20 }, 'M.age < 21', callback)
,那么我的回调将返回true
。类似地,filt({ age: 21}, 'M.age < 21', callback)
按预期返回false。
然而,我希望以下内容也能成真:filt({}, 'M.age < 21', callback)
。然而,undefined==true
是false(类似于所有具有undefined
的布尔表达式)。我考虑过使用正则表达式检查字符串(我的所有变量都作为对象M
上的字段传递)。因此,如果filterString
包含M.varname
(或M."varname"
或M["varname"]
),那么如果M
上没有这样的字段,则替换为true。然而,在编码之前,我想我会试探一下,看看是否有更好的方法。
有什么想法吗?提前谢谢。
更新:
多亏了这些反馈,我发现我的整个方法需要重新思考。为了简化,我想知道是否有一种方法可以计算具有未知值的表达式,这样,如果一个表达式涉及并且未知,那么结果就是未知的。例如在伪代码中:
M > 21 = unknown if M == unknown
M > 21 = true if M == 23
M > 21 = false if M == 'fish'
M > 21 | true = true independent of the value of M.
部分解决方案:不回答问题
我在这里发布了一个过于乐观的部分解决方案。这涵盖了我的单元测试,但它非常可怕,可能很危险。在考虑做这样的事情之前,请阅读上面其他用户的评论。
function(M, filterString, cb){
var regexp = /M(."w+"|.'w+'|.w+|["w+"]|['w+'])+/g
/*
Matches all of the following
M."a"
M.'a'
M.a["b"].c
M["a"].b['c']
M.a.b
*/
var expectedVariables = filterString.match(regexp)
// Check that the variables in the filterString are available
var allMetaDataAvailable = true
for(var i=0 ; i< expectedVariables.length; i++){
if (typeof eval(expectedVariables[i]) =='undefined'){
allMetaDataAvailable = false
}
}
if (!allMetaDataAvailable){
// Optimistic
cb(true)
} else {
// Evalue the expression
var res
try{
res = eval(filterString)
} catch(me){
// something went wrong - allow.
res = true
}
cb(res)
}
}
这只是部分解决方案的原因是,如果M = { gender : 'm' }
,字符串表达式M.age < 20 | M.gender=='f'
将返回true,因为它不知道age
的值,所以它乐观地说,该表达式可能(在未来-一旦定义了值)变为true-在这种情况下,这显然是不可能的,因为我们已经知道gender
的值是错误的。
更新:我现在发现了一个非常轻量级的库,名为JSEP.js,用于创建javascript表达式的抽象语法树。这似乎是实现基于javascript的三元逻辑的理想起点,该逻辑能够正确处理布尔表达式中的未知值。