JSLint"eval是邪恶的." 备择方案

Jak*_*sel 11 javascript eval dry jslint

我有一些在客户端(浏览器)和服务器上运行的JavaScript函数(在Java Rhino上下文中).这些是小函数 - 基本上很少有验证器,它们定义良好且不依赖于全局或闭包 - 自包含和可移植.

这是一个例子:

function validPhoneFormat(fullObject, value, params, property) {
    var phonePattern = /^\+?([0-9\- \(\)])*$/;
    if (value && value.length && !phonePattern.test(value))
        return [ {"policyRequirement": "VALID_PHONE_FORMAT"}];
    else
        return [];
}
Run Code Online (Sandbox Code Playgroud)

为了保持DRY,我的服务器代码获取每个函数的句柄并调用它们上的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"
            }
          ]
      }
Run Code Online (Sandbox Code Playgroud)

然后我的浏览器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));
Run Code Online (Sandbox Code Playgroud)

一切都很好.但是,我然后通过JSLint运行此代码,我收到此消息:

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

我很欣赏,eval可能很危险.但是,我不知道如何在不使用它的情况下实现这样的机制.有什么方法可以做到这一点,并通过JSLint验证器?

Bri*_*y37 12

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

另一方面,如果你正朝着另一个方向前进并在服务器上进行客户传递代码的躲避,那将是一个完全不同的故事......

更新:

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

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

policyFunction.apply(this, policyArguments); 
Run Code Online (Sandbox Code Playgroud)

更新2:

我能够成功地使用JSLint验证以下代码,这实际上允许您在eval适当的大多数情况下"关闭"验证.同时,JSLint仍然验证正常eval调用,并且此方法的所有使用都应该为将来的开发人员提供标记,以避免在可能/时间允许的情况下使用它/重构它.

var EVAL_IS_BAD__AVOID_THIS = eval;
EVAL_IS_BAD__AVOID_THIS(<yourString>);
Run Code Online (Sandbox Code Playgroud)


Ale*_*yne 5

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

相反,我想你可以返回 JS 文件,它允许真正的功能:

 { name : "phoneNumber",
    policies : [ 
        { policyFunction : function() {
              whateverYouNeed('here');
          }
        }
      ]
  }
Run Code Online (Sandbox Code Playgroud)

但是,虽然这解决了技术问题,但这仍然不是一个好主意。


这里真正的解决方案是将您的逻辑完全移出您的内容。导入一个包含少量验证函数的 JS 文件,并根据dataTypeJSON 中的属性或其他内容根据需要调用它们。如果这个功能像你说的那样小巧便携,这应该很容易实现。

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