AST基础知识|js纯函数与强大的 path.evaluate 方法。

关注它,不迷路。       

本文章中所有内容仅供学习交流,不可用于任何商业用途和非法用途,否则后果自负,如有侵权,请联系作者立即删除!

1.什么是纯函数

根据chatGPT-4的解释:

在JavaScript中,纯函数是一种特殊类型的函数,它具有以下两个主要特征:

  1. 确定性:对于相同的输入值,纯函数总是产生相同的输出。这意味着函数的输出完全依赖于输入参数,并且没有其他外部因素(如全局变量、数据库状态、文件系统等)影响输出。

  2. 无副作用:纯函数执行时不会对外部环境产生影响,也就是说,它不会修改任何外部状态(如全局变量、数据库、文件系统等),也不依赖于它们。函数内部的所有变化都只限于函数作用域内,不会“泄露”到函数外部。

这样的特性让纯函数在调试、测试和理解代码方面变得非常有利。它们的行为是可预测的,并且由于没有副作用,可以安全地在代码的任何地方调用它们,而不用担心会影响到程序的其他部分。

举个例子:

function add(x, y) {
  return x + y;
}

这个`add`函数接受两个参数`x`和`y`,然后返回它们的和。每次给定相同的`x`和`y`值时,`add`函数都会返回相同的结果,并且它不会修改或依赖于函数外部的任何状态。因此,它是一个纯函数。

2.纯函数调用还原

因为实参固定,结果也固定,而且不依赖函数外部的变量,因此,写个插件还原此类函数的调用表达式,可以通用。

具体代码参考:

https://t.zsxq.com/18V8zIsSs

3.错误的认知

我之前以为在AST还原代码中,要求 函数调用的实参 全部为 字面量 时才可以进行计算,后来发现,使用 path.evaluate 可以获取实参的真实值。

以下面的代码为例:

var aa = 1,bb = 2;


function add(a,b)
{
    return a + b;
}


var cc = add(aa,bb);

我之前的做法是先将 :

var cc = add(aa,bb);

还原成:

var cc = add(1,2);

然后再使用 2 中提到的插件进行还原。

而这里的实参aa,bb有个特点,变量定义有初始值,这些变量在其作用域内没有被改变,因此,直接使用 path.evaluate 方法可以获取它们的值:

const args = argumentsPaths.map(argPath => argPath .evaluate().value);
if (args.length == 0 || args.includes(undefined)) {
    canRemoved = false;
    continue;
}
let value = globalThis[id.name].apply(null, args); //计算结果

通过map返回的结果里是否包含计算结果为 undefined 的情况来获取实参值,然后进行调用计算。

4.babel库的不足

虽然 path.evaluate 方法很强大,但也有它的局限性,比如,稍微将上面的代码变形:

var aa,bb;
aa = 1;
bb = 2;
function add(a,b)
{
    return a + b;
}
var cc = add(aa,bb);

这里,变量的声明和定义是分开的,再用 2 中的插件无法进行还原。

原因是 aa,bb初始化为undefined,后面又进行了重新赋值(change),因此  path.evaluate 取不到具体的实参值。

又如,在循环体中定义的变量:

function add(a, b) {
    return a + b;
}


while (1) {
    var aa = 1, bb = 2;
    var cc = add(aa, bb);
}

使用 2 中的插件也无法进行还原,我认为这是babel库里的一个小bug:定义在循环体内的变量,不管它的值是否变过,babel库都默认 binding.constantViolations 的长度大于 0.这使得 path.evaluate 也取不到实参的真实值。

5.还原的通用思路

所以,为了保证再使用 2 中的插件尽可能多的还原函数调用表达式,我一般先将实参给还原成字面量,再作处理,就不会有问题了。

好了,今天的内容就到这里了,感谢阅读。

欢迎加入知识星球,学习更多AST和爬虫技巧。

9cc0871ac831d4d5ea0a61b6be781e1d.jpeg

  • 16
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值