You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js中class类内部使用eval定义函数无法正常调用的问题

问题成因

两个示例运行结果不一致,核心是严格模式下eval的作用域规则差异和this指向差异共同导致的:

  • 全局作用域的示例运行在非严格模式下:直接调用eval时,eval内部声明的函数会泄漏到外层全局作用域;同时全局作用域的this指向全局对象(浏览器为window、Node.js为globalThis),声明的teste函数会自动成为全局对象的属性,因此this.teste()可以正常调用。
  • ES6 Class 内部的所有代码默认强制开启严格模式:严格模式下eval会创建独立的私有作用域,eval内部声明的函数、变量仅在eval执行阶段可访问,不会泄漏到外层的run方法作用域,更不会自动绑定到当前类实例的this上。此时访问this.teste时,实例本身不存在该属性,就会抛出方法不存在的错误。
可行解决方案

方案1:显式将函数挂载到实例this(推荐)

修改eval执行的字符串代码,直接将声明的函数赋值给当前上下文的this,执行后函数会直接成为实例的自有属性,可正常调用:

class Oi {
  constructor() {
    this.s = ""
    this.t = ""
  }
  
  run(){
    // 直接在eval代码中把函数挂载到this上
    this.s = "this.teste = function() {console.log('testando')}"
    eval(this.s)
    
    this.teste(); // 正常输出 testando
  }
}

let o = new Oi();
o.run();

方案2:接收eval返回值手动挂载

调整eval执行的代码逻辑,让代码块返回目标函数,执行eval后拿到返回值手动挂载到实例上:

class Oi {
  constructor() {
    this.s = ""
    this.t = ""
  }
  
  run(){
    // 用立即执行函数返回定义好的teste函数
    this.s = "(() => function teste() {console.log('testando')})()"
    // 接收eval返回的函数,挂载到当前实例
    this.teste = eval(this.s)
    
    this.teste(); // 正常输出 testando
  }
}

let o = new Oi();
o.run();

方案3:间接调用eval在全局作用域执行(不推荐)

通过间接调用eval的方式(如(0, eval)())强制让代码在全局作用域执行,此时函数会挂载到全局对象上,但这种方式会污染全局命名空间,非特殊场景不建议使用:

class Oi {
  constructor() {
    this.s = ""
    this.t = ""
  }
  
  run(){
    this.s = "function teste() {console.log('testando')}"
    // 间接调用eval,强制在全局作用域执行代码
    (0, eval)(this.s)
    
    // 函数挂载在全局对象上,不能通过this调用,要从全局对象取
    globalThis.teste(); // 正常输出 testando
  }
}

let o = new Oi();
o.run();

注意:eval存在代码注入安全风险,除非完全可控动态字符串的来源,否则优先选择其他更安全的动态逻辑实现方案。

内容的提问来源于stack exchange,提问作者Rafael Calino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 17:42:15