js执行字符串代码

本文介绍了在JavaScript中如何将字符串作为代码执行,主要讨论了eval函数和newFunction()的使用方法、适用场景以及两者之间的差异,强调了在实际项目中的安全性和灵活性选择。
摘要由CSDN通过智能技术生成

一、适用场景

在业务中我们很少去将一个字符串作为代码执行,因为出于安全考虑,尽量不要直接在客户端执行用户输入的代码。但是在造轮子或者框架开发中,我们需要在解析完开发者编写的代码后,来手动执行这些字符串代码。

二、具体实现

1. eval

eval是一个我们都知道的函数,这个函数会将传入的字符串当做 JavaScript 代码进行执行。所以我们很多时候会用它来执行字符串代码。
例如:

  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来解决这个问题。

  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,更加简单方便。
  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值