JavaScript 如何从一个字符串中创建一个函数
当你需要在运行时动态生成一个函数时,或者当你有一个包含你想执行的函数代码的字符串时,在JavaScript中从字符串中创建一个函数是很有帮助的。
从字符串构造函数的能力是JavaScript的一个有用的功能,它允许在运行时动态创建函数。eval()函数和new Function()函数Object()[本地代码]是两种最流行的方法,尽管两者都有明显的安全缺陷。
Function.prototype.constructor是一个更安全的选择,尽管它不太为人所知。在选择JavaScript方法从字符串中创建一个函数之前,考虑风险和使用情况是至关重要的。
方法1:使用eval()函数
JavaScript eval()方法是从字符串建立一个函数的最简单的方法之一。这个强大的eval()函数可以运行任何以字符串形式提供给它的JavaScript代码。
例子
<html>
<body>
<p id="result"></p>
<script>
let functionString = "function add(a, b) { return a + b; }";
let add = eval("(" + functionString + ")");
document.getElementById("result").innerHTML = "Sum of 1 and 2: " + add(1, 2);
</script>
</body>
</html>
在这里我们可以看到,我们有一个函数,它接收两个参数并返回它们的总和。现在,这个函数被包含在一个字符串中。eval()函数接收这个字符串作为参数,在返回函数之前对其进行评估。然后,返回的函数被分配给一个叫做add的变量,它可以像其他函数一样使用。
然而,它运行任何提供给它的JavaScript代码,因此在生产代码中使用它是有风险的,因为它可能导致安全缺陷。
方法2:使用新函数()构造器
另一种从字符串中创建函数的方法是使用Function()构造器。Function()构造函数从一个包含函数代码的字符串中创建一个新的函数对象。下面是一个如何使用Function()构造函数从字符串中创建一个函数的例子。
例子
<html>
<body>
<p id="print"></p>
<script>
let functionString = "function add(a, b) { return a + b; }";
let functionBody = functionString.substring(
functionString.indexOf("{") + 1,
functionString.lastIndexOf("}")
);
let add = new Function("a", "b", functionBody);
document.getElementById("print").innerHTML = "Sum of 1 and 2: " + add(1, 2);
</script>
</body>
</html>
在这个例子中,我们将包含函数代码的字符串传递给Function()构造函数,该构造函数从该字符串创建一个新的函数对象。然后我们将返回的函数分配给一个变量add,它可以像其他函数一样使用。
由于它只能创建函数,所以比eval()的风险要小,但仍有类似的风险
方法3:使用Function.prototype.constructor
这可以生成一个函数,除了以字符串形式传递的函数体,不能运行任何其他代码。然而,它的使用范围较小,而且不像其他两种方法那样被老的浏览器所支持。
例子
<html>
<body>
<p id="result"></p>
<script>
let add = Function.prototype.constructor('a', 'b', 'return a+b')(1, 2);
document.getElementById("result").innerHTML = "Sum: " + add;
</script>
</body>
</html>
在这个例子中,函数参数和函数体被提供给构造函数。我们使用Function.prototype.constructor来创建一个具有给定参数和给定函数体的新函数,然后立即通过调用给定参数来调用该函数。
请记住,你从一个字符串中构造的函数将可以访问全局范围,而不会被包含在你创建它的代码的范围内。
另一件要记住的重要事情是,从字符串中创建一个函数可能会减慢应用程序的速度,特别是当函数体较长时。
此外,如果函数很复杂,从字符串中建立一个函数会使理解和调试代码更具挑战性。
通常不建议在生产代码中使用eval()和new Function()方法,因为它们存在安全问题。相反,你应该考虑其他的选择,如预编译函数或使用JavaScript预处理器,如Babel,将你的代码转译为一个等价的、更安全的版本。