Skip to content

eval 的替代方法

1. 前因

之前写了个跳转的油猴脚本, 后来经过一番迭代后,突然发现之前自动跳转的网页又失效了:

遂查看原因:

原来是上一次为了适配 wexin110 的跳转页面,新增了一条规则,

这条规则在 weixin110 页面是可以正常工作的,

但是却因为其他页面无法获取到 winxin110 指定的 dom 元素,导致程序终止运行了

解决起来也非常简单,把即时执行的获取 dom 的代码改成字符串形式

然后在函数里执行的时候在进行解析就可以了

那么如何让字符串形式的代码执行起来呢? 我想到了eval()函数

js
const jumpUrl = url => {
  const regular = domain[url] || null
  // 判断是否为正则表达式
  if (regular instanceof RegExp) {
    const result = urlInfo.href.match(regular)
    if (result) window.location.href = decodeURIComponent(result[1])
  } else {
    window.location.href = eval(domain[url]) 
  }
}

// 配置项
const domain = {
  'c.pc.qq.com': /pfurl=(.*)&pfuin/,
  'link.zhihu.com': /target=(.*)/,
  'link.juejin.cn': /target=(.*)/,
  'link.csdn.net': /target=(.*)/,
  'weixin110.qq.com': "document.querySelector('.ui-ellpisis-content p').innerText",
}

问题完美解决,但我之前看书的时候,看到过eval()函数的使用是不推荐的,它有很多安全漏洞,并且性能也不够优秀,因此它通常不是最佳的选择。

2. 替代方法

根据不同的需求, 有不用的方法来替代eval()函数

2.1 将字符串解析为表达式并计算结果

使用 JavaScript 中内置的 Function 构造函数来创建一个新的函数, 然后调用这个函数来执行表达式。例如:

js
const result = new Function('return ' + str)()

2.2 将字符串解析为 JavaScript 代码并执行

js
const result = new Function(str)()

2.3 动态加载并执行 JavaScript 代码

js
const script = document.createElement('script')
script.textContent = str
document.head.appendChild(script)

根据需求,解决这次问题,我们可以采用第一种方法:

js
const jumpUrl = url => {
  const regular = domain[url] || null
  // 判断是否为正则表达式
  if (regular instanceof RegExp) {
    const result = urlInfo.href.match(regular)
    if (result) window.location.href = decodeURIComponent(result[1])
  } else {
    window.location.href = eval(domain[url]) 
    window.location.href = new Function('return ' + domain[url])() 
  }
}

3. 总结

其实说到底, 还是因为新增功能后没有对已有功能没有做测试导致的问题, 以后在开发的时候,一定要注意测试,不要因为一时的激动,而忽略了已有功能的测试,这样才能保证项目的稳定性。