我有一个允许根据环境评估字符串的函数
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。
但是我还希望以下内容也返回true:
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.
答案 0 :(得分:0)
部分解决方案:不回答问题
我在这里发布一个过于乐观的部分解决方案。这包括我的单元测试,但它是可怕的,可能是危险的。在考虑做这样的事情之前,请阅读上面其他用户的评论。
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.age < 20 | M.gender=='f'
将在M = { gender : 'm' }
时返回true,因为它不知道age
的值然后它乐观地说表达式可能(将来 - 一旦定义了值)变为真 - 在这种情况下显然是不可能的,因为我们已经知道gender
的值是错误的。
更新:我现在发现了一个名为JSEP.js的非常轻量级的库,用于创建javascript表达式的抽象语法树。这似乎是实现基于javascript的三元逻辑的理想起点,能够正确处理布尔表达式中的未知值。