高频问题|JavaScript语言的骚,差点闪了我的腰

关注它,不迷路。       

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

1.问题

对于如下一段代码:

function add(a){}


var a = 123;


add(a = 456);

请问,上面这段代码执行后,变量a的值是否发生改变?

2.回答

GPT3.5的回答很弱智,就不贴了。文心一言的回答: 要理解这段代码执行后变量a的最终值,我们需要考虑JavaScript中的参数传递和赋值操作的顺序。‌函数定义‌:function add(a){} 定义了一个名为add的函数,它接受一个参数a。但函数体内没有执行任何操作。‌变量声明和初始化‌:var a = 123; 声明了一个变量a并将其初始化为123。‌函数调用‌:add(a = 456); 这行代码做了两件事:首先,它执行了赋值操作a = 456这个操作会改变变量a的值,将其从123变为456。然后,它将赋值操作的结果(即新的a的值,456)作为参数传递给add函数。由于add函数内部没有使用其参数,这个传递实际上没有产生除了改变a值以外的任何效果。因此,当这段代码执行完毕后,变量a的值是456。总结:最后变量a的值是456,因为在调用add函数时,我们首先将a的值更改为456,然后将这个新值作为参数传递给函数(尽管函数内部没有使用这个值)。

3.为什么会有这种问题

因为在混淆代码中遇到过了:

21e84f056d9f938221c0ac0904b0de16.png

这种混淆代码如果要还原的话,写插件也很容易。

  1. 遍历调用表达式;

  2. 判断实参中是否包含赋值语句,如果包含,则将其提到该调用表达式前面来,并留下left节点即可。

4.AST源码

const AssignmentInArgs = 
{
  /**  @param  {NodePath} path */  //每个插件前都要加哈。
  CallExpression(path)
  {
    let {parentPath,node} = path;


    if (!parentPath.isExpressionStatement({"expression":node}))
    {
      return;
    }


    let {arguments} = node;


    for (let i=0; i<arguments.length ;i++)
    {
      if (types.isAssignmentExpression(arguments[i]) && arguments[i].operator == "=")
      {
        parentPath.insertBefore(types.ExpressionStatement(arguments[i]));
        path.node.arguments[i] = arguments[i].left;
      }
    }
  }
}


traverse(ast, AssignmentInArgs);

今天的分享就到这里,感谢阅读。

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

be654618aa800782a612dcd98d56b7d6.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值