Javascript JSLint";逃避是邪恶的。”;选择

Javascript JSLint";逃避是邪恶的。”;选择,javascript,eval,dry,jslint,Javascript,Eval,Dry,Jslint,我有一些JavaScript函数可以在客户端(浏览器)和服务器(在JavaRhino上下文中)上运行。这些都是小函数——基本上是定义良好的小验证器,不依赖全局函数或闭包——自包含且可移植 下面是一个例子: function validPhoneFormat(fullObject, value, params, property) { var phonePattern = /^\+?([0-9\- \(\)])*$/; if (value && value.leng

我有一些JavaScript函数可以在客户端(浏览器)和服务器(在JavaRhino上下文中)上运行。这些都是小函数——基本上是定义良好的小验证器,不依赖全局函数或闭包——自包含且可移植

下面是一个例子:

function validPhoneFormat(fullObject, value, params, property) {
    var phonePattern = /^\+?([0-9\- \(\)])*$/;
    if (value && value.length && !phonePattern.test(value))
        return [ {"policyRequirement": "VALID_PHONE_FORMAT"}];
    else
        return [];
}
为了保持干爽,我的服务器代码对每个函数都有一个句柄,并对它们调用toString(),将它们作为JSON对象的一部分返回到浏览器。大概是这样的:

      { "name" : "phoneNumber",
        "policies" : [ 
            { "policyFunction" : "\nfunction validPhoneFormat(fullObject, value, params, property) {\n    var phonePattern = /^\\+?([0-9\\- \\(\\)])*$/;\n    if (value && value.length && !phonePattern.test(value)) {\n        return [{\"policyRequirement\":\"VALID_PHONE_FORMAT\"}];\n    } else {\n        return [];\n    }\n}\n"
            }
          ]
      }
然后,我的浏览器JS代码接受此响应并在该上下文中创建此函数的实例,如下所示:

eval("var policyFunction = " + this.policies[j].policyFunction);

policyFailures = policyFunction.call(this, form2js(this.input.closest("form")[0]), this.input.val(), params, this.property.name));
这一切都非常有效。但是,我随后通过JSLint运行了这段代码,并返回以下消息:

[ERROR]ValidatorsManager.js:142:37:eval是邪恶的


我明白,eval常常是危险的。然而,我不知道如果不使用它,我还能如何实现这样一个机制。有什么方法可以做到这一点并通过JSLint验证器吗?

我不担心,因为您只是将这些函数字符串从服务器传递到客户端,因此可以控制将要评估的内容

另一方面,如果您正朝着另一个方向,在服务器上对客户端传递的代码进行评估,那将是一个完全不同的故事

更新:

由于在注释中禁用验证选项可能会导致您错过将来的错误,因此我建议传递函数名而不是整个函数,并在服务器和客户端上镜像函数库。因此,要调用该函数,您需要使用以下代码:

var policyFunction = YourLibraryName[this.policies[j].policyFunctionName];
var policyArguments = this.policies[j].policyArguments;

policyFunction.apply(this, policyArguments); 
更新2:

我成功地用JSLint验证了下面的代码,这基本上允许您在
eval
合适的极少数情况下“关闭”验证。同时,JSLint仍然验证正常的
eval
调用,并且该方法的所有使用都应该为未来的开发人员提供标志,以避免在可能的情况下/在时间允许的情况下使用它/重构它

var EVAL_IS_BAD__AVOID_THIS = eval;
EVAL_IS_BAD__AVOID_THIS(<yourString>);
var EVAL\u是坏的\u避免\u这=评估;
评估是坏的,避免这个();
您可以使用

setInterval("code to be evaluated", 0);
在内部,如果向setInterval传递字符串,它将执行类似于eval()的函数


然而,我不会为此担心。如果您知道eval()是邪恶的,并且采取了适当的预防措施,那么这并不是一个真正的问题。Eval类似于GoTo;你只需要小心并意识到你在做什么才能正确地使用它们。

好吧,首先要记住的是,jsLint确实指出“这会伤害你的感情”。它旨在指出您没有遵循最佳实践的地方——但不完美的代码仍然可以正常工作;没有强迫你听从jsLint的建议

话虽如此,eval是邪恶的,在几乎所有情况下,使用eval总是有办法的

在这种情况下,您可以使用诸如require.js、yepnope.js之类的库,或者设计用于单独加载脚本的其他库。这将允许您动态地包含所需的javascript函数,但无需
eval()
它们

可能还有其他几种解决方案,但这是我想到的第一个


希望这有帮助。

我会避免在所有情况下使用eval。没有理由不能围绕它编写代码。不要向客户机发送代码,只需将其托管在服务器上的一个包含的脚本文件中即可

如果这不可行,您还可以创建一个动态生成的javascript文件,然后通过响应传入必要的参数,然后在客户端动态加载脚本。真的没有理由使用eval


希望有帮助。

不要将函数编码为JSON中的字符串。JSON用于内容,您将其与行为混淆

相反,我认为您可以返回JS文件,它允许真正的函数:

 { name : "phoneNumber",
    policies : [ 
        { policyFunction : function() {
              whateverYouNeed('here');
          }
        }
      ]
  }
虽然这解决了技术问题,但这仍然不是一个好主意


这里真正的解决方案是将您的逻辑完全移出您的内容。导入一个包含小验证函数的JS文件,并根据JSON中的
dataType
属性或其他内容根据需要调用它们。如果这些函数像您所说的那样小且可移植,那么实现起来应该很简单


让你的数据和你的代码纠缠在一起通常会导致痛苦。您应该静态地包含JS,然后动态地请求/导入/查询JSON数据,以便在静态包含的代码中运行。

只需很少的解析,您就可以得到这样的JSON数据:

var body = this.policies[j].policyFunction.substr;
body = body.substr(body.indexOf("(") + 1);
var arglist = body.substr(1, body.indexOf(")"));
body = body.substr(arglist.length + 1);
var policyFunction = new Function(arglist, body);
这将提供一点验证,避免使用
eval
的文字,并与代码同步工作。但它肯定是伪装的
eval
,并且容易受到XSS攻击。如果恶意的人能够以这种方式加载和评估他们的代码,那么它将不会拯救你。所以,真的,不要这样做。添加一个带有正确URL的
标记,这样肯定会更安全。好吧,你知道,安全比抱歉好


注:如果上面的代码不起作用,我表示歉意,它只显示了意图,我没有测试过它,如果我在计算括号时出错或诸如此类-好吧,你应该明白,我没有用任何方式宣传它。

DRY肯定是我同意的,但是,复制+粘贴比引用同一段代码更高效、更易于维护

从编写代码中节省下来的代码似乎相当于一个干净的界面和简单的锅炉板。如果在服务器和客户机上使用相同的代码,您可以简单地传递函数的公共部分,而不是整个函数

Payload:
{
    "name": "phoneNumber",
    "type": "regexCheck",
    "checkData": "/^\\+?([0-9\\- \\(\\)])*$/"
}
这将使您能够从单个位置更新正则表达式。如果接口发生更改,它确实需要
if(payload.type === "regexCheck"){
    const result = validPhoneFormat(fullObject, value, payload.checkData)
}

function validPhoneFormat(fullObject, value, regexPattern) {

    if (value && value.length && !regexPattern.test(value))
        return [ {"policyRequirement": "VALID_PHONE_FORMAT"}];
    else
        return [];
}