关注它,不迷路。
本文章中所有内容仅供学习交流,不可用于任何商业用途和非法用途,否则后果自负,如有侵权,请联系作者立即删除!
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.为什么会有这种问题
因为在混淆代码中遇到过了:
这种混淆代码如果要还原的话,写插件也很容易。
遍历调用表达式;
判断实参中是否包含赋值语句,如果包含,则将其提到该调用表达式前面来,并留下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和爬虫技巧。