替代邪恶的求值-关系运算符
Alternative to Evil Eval - relational operators
作为输入验证的一种形式,我需要强制将像'9>6'
这样的字符串计算为布尔值。
除了计算字符串外,我似乎找不到解决方法。
我总是听说eval的邪恶(特别是当我验证表单输入时),关于它可以评估任何脚本和性能问题的事实。
但是…
在我的情况下(处理关系操作符)有任何替代方案吗?
var arr = ['<9', '>2'];
var check = function (a) {
return arr.every(function (x) {
var string = '';
string += a + x;
try {
return eval(string);
} catch (e) {
return false;
}
});
};
console.log(check('3'))
我不会说eval本质上是邪恶的,我只是说它有它的优点和缺点。在我的实践中,我很少遇到它的优点很多的情况。
eval的两个主要问题:- 它需要运行时解释,即javascript引擎的字符串处理和解释。它是缓慢的。正常的javascript以标记化的形式运行。
- 如果你使用eval,你也开始了一个游戏,你想要阻止插入任何有害的代码,而不降低功能,黑客试图找到一个方法通过你的块。你唯一能确定你没有输的就是你的网站直到现在才被破解。你根本不可能知道你赢了。
但是:eval主要运行在浏览器端,或者处理用户输入数据(由同一用户创建),或者服务器端生成的服务器数据。
你的情况的解决方案是显而易见的:使用硬OO的东西,例如函子。
function comparator(lighter, num) {
return function(x) {
return lighter ? (x<num) : (x>num);
}
}
var arr = [ comparator(true, '9'), comparator(false, '2') ];
var check = function(a) {
return arr.every(function(comp) { return comp(a); });
}
console.log(check('3'));
在第一点上,它比你的版本复杂得多,但这只是因为你习惯了求值,而不是复杂的函子解决方案。事实上,解决方案的复杂性是非常相似的。
我认为有三点需要改进:
-
不要将
a
值字符串化并将其连接到表达式中,而应该直接引用a
变量,以便与值的真实形式进行比较。否则你可能会得到奇怪的行为。return eval("a " + x);
-
由于您可能多次使用
check
,因此您不应该每次都调用eval
(甚至每次调用多次)。您可以将字符串组合成一个大的&&
表达式,甚至更好的是,您可以事先将条件编译为单个函数,这样您就完全不必从check
中调用eval
。 -
你应该考虑使用
Function
构造函数而不是eval
。
var arr = ['<9', '>2'];
var check = new Function("a", "return "+arr.map(function(x) {
return "a"+x;
}).join(" && ")+";");
console.log(check.toString()); // function anonymous(a) { return a<9 && a>2; }
console.log(check('3'));
或:
var arr = ['<9', '>2'];
var fns = arr.map(function(x) {
return new Function("a", "return a "+x+";");
});
function check(a) {
return fns.every(function(f) {
return f(a);
});
}
console.log(check('3'));
当然,我希望arr
不是由用户控制的(或者更糟,不是当前用户控制的);如果您希望用户输入这些条件,您应该确保将它们显式地列入白名单,或者可以立即使用更复杂的表达式语法/解析器/求值器。
除非是这种情况,否则eval
(或者就此而言,Function
)并不完全是邪恶的,它只是缩短(并可能简化)您的代码。您也可以编写完整的函数(就像Nit和peterh建议的那样)。
一种选择是定义辅助函数,但是这种方法有多有用很大程度上取决于您想要在更大的范围内实现什么。
function geq(n) {
return function(m) {
return m >= n;
}
}
function leq(n) {
return function(m) {
return m <= n;
}
}
var arr = [leq(9), geq(2)];
function check(n) {
arr.forEach(function(checkAgainst) {
console.log(checkAgainst(n));
});
}
- 这是什么 ==- javascript 运算符
- jQuery/JS包含运算符或类似运算符
- Javascript逻辑运算符和字符串/数字
- 模运算符前的双水平线
- 气质的“nestRemoting()”有时可以'找不到关系
- 如何在Parse中创建一对多关系
- Ext.js从json构建模型关系的问题
- jQuery's trim()的前缀为not运算符
- Javascript,如果条件在没有&&逻辑运算符当&&它不起作用
- 如果在构造函数中有“返回”,则在 JavaScript 中的新运算符中做了什么
- 如何使用排列运算符来获取具有命名参数的函数的所有参数
- JavaScript 中三元条件和逻辑和运算符的运算符优先级
- 用于验证JS中逻辑运算符表达式的正则表达式
- 什么's是相当于LINQ's SelectMany运算符
- JSDoc:模块和名称空间之间的关系是什么
- 单元测试依赖关系没有被嘲笑
- 不使用关系运算符的JavaScript条件表达式
- 替代邪恶的求值-关系运算符
- Javascript 关系运算符显示字符串的奇怪行为
- JavaScript关系比较运算符如何强制类型