JavaScript执行字符串代码:eval与new Function()详解

作者:木棉

时间:2026-11-01

浏览:344

本文深入解析JavaScript中执行字符串代码的两种主要方式:eval与new Function()。详细对比了两者在作用域、参数传递及返回值处理上的差异,指出eval在当前上下文执行易引发命名冲突,而new Function()仅在全局作用域运行且支持参数传递。通过具体代码示例,展示了如何利用new Function()解决变量冲突并获取返回值,为框架开发中的动态代码执行提供了实用方案。

文章目录

一、适用场景

在常规业务开发中,直接执行字符串形式的代码较为罕见,主要出于安全考量,应避免在客户端直接运行用户输入的代码。然而,在框架或工具库的开发过程中,解析开发者编写的代码后,往往需要手动执行这些字符串形式的代码片段。

二、具体实现

1. eval

eval是JavaScript中一个广为人知的内置函数,其功能是将传入的字符串参数解析为JavaScript代码并立即执行。因此,在需要执行字符串代码的场景中,eval常被作为首选方案。

例如:

  const log = `console.log('11')`
  eval(log)
  const testCode = `
  function test() {
    console.log('test')
  }
  test()
  `
  eval(testCode)

一、适用场景

需要注意的是,eval执行代码时使用的是当前所在的作用域上下文。如果字符串代码中定义的变量或函数与当前上下文中的同名变量发生冲突,将会导致报错。

例如:

  const test = 'test'
  const testCode = `
  function test() {
    console.log('test')
  }
  test()
  `
  eval(testCode)

一、适用场景

由于当前作用域中已定义了名为test的变量,而字符串代码中也存在同名的test函数,这种命名冲突直接导致了运行错误。

为了避免字符串代码中的变量与当前上下文变量重名的问题,可以将eval放在一个自调用函数(IIFE)中执行,以此隔离作用域。

  const test = 'test'
  const a = 1
  const testCode = `
  function test() {
    console.log('test')
    console.log(a)
  }
  test()
  `
  ;(function () {
    const a = 2
    eval(testCode)
  })()

这样即可避免冲突。需要注意的是,此时打印的a值为2,即自调用函数作用域内的a值。

一、适用场景

2. new Function()

语法:new Function(arg0, arg1, /* …, */ argN, functionBody)Function() 构造函数用于创建 Function 对象。直接调用构造函数可以动态创建函数,虽然仍可能存在类似 eval() 的安全性和性能问题(但相对较小)。与能够访问本地作用域的 eval 不同,Function 构造函数创建的函数仅在全局作用域中执行。

例如:

  const test = 'test'
  const a = 1
  const testCode = `
  function test() {
    console.log('test')
    console.log(a)
  }
  test()
  `
  ;(function () {
    const a = 2
    const func = new Function(testCode)
    func()
  })()

注:当前的a打印的是1,也就是Function 构造函数创建的函数仅在全局作用域中执行。里面的未定义的变量会直接使用全局的变量。

一、适用场景

如何解决这个问题?

创建function的时候支持传递参数,我们可以通过参数传递来解决。

  const test = 'test'
  const a = 1
  const testCode = `
  function test() {
    console.log('test')
    console.log(a)
  }
  test()
  `
  ;(function () {
    const a = 2
    const func = new Function('a', testCode)
    func(a)
  })()

我们将a传递作为参数传递到了func中,实际上func现在就相当于:

  function func(a) {
    function test() {
      console.log('test')
      console.log(a)
    }
    test()
  }

一、适用场景

这种方式就不用但是上下文命名冲突的问题,因为代码是在函数中执行的,因此我们不需要在自调用函数中运行 new Function()。 并且通过这种方式我们还能接受到字符串代码中的返回。

  const test = 'test'
  const sum = `return a + b`
  const func = new Function('a', 'b', sum)
  console.log(func(2, 3))

一、适用场景

三、两者差异

  • eval是在当前上下文执行代码,会出现变量命名冲突,而new Function()是在函数内部执行,不会出现冲突
  • eval的作用域是当前执行位置的作用域,而new Function()的作用域是全局
  • eval不能传递参数,也不能接受返回值,new Function()可以传递参数并接收返回值 所以如果是大量的执行字符串代码,建议使用new Function()的方式,它更强大(比如Vue框架就使用new Function()的方式)。如果你只是偶尔使用,并且对参数、命名也没要求,那就直接使用eval,更加简单方便。

附:结合eval和new Function()一起实现

try {
const val = new Function(“要执行的字符串”);
let eleResult = val(); // 这里必须调用val(),不然不会执行
if (!eleResult) {
eleResult = eval(“要执行的字符串”);
}
} catch (err) {
console.info(‘执行字符串js出错');
}

到此这篇关于js执行字符串代码具体实现的文章就介绍到这了,更多相关js执行字符串代码内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章