火爆全网的 Evil.js 源码解读

我是HullQin,公众号线下聚会游戏的作者(欢迎关注公众号,发送加微信,交个朋友),转发本文前需获得作者HullQin授权。我独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏。还开发了《Dice Crush》参加Game Jam 2022。喜欢可以关注我 HullQin 噢~我有空了会分享做游戏的相关技术。

背景

2022年8月18日,一个名叫Evil.js的项目突然走红,README介绍如下:

什么?黑心996公司要让你提桶跑路了?

想在离开前给你们的项目留点小 礼物

偷偷地把本项目引入你们的项目吧,你们的项目会有但不仅限于如下的神奇效果:

  • 当数组长度可以被7整除时,Array.includes 永远返回false。
  • 当周日时,Array.map 方法的结果总是会丢失最后一个元素。
  • Array.filter 的结果有2%的概率丢失最后一个元素。
  • setTimeout 总是会比预期时间慢1秒才触发。
  • Promise.then 在周日时有10%不会注册。
  • JSON.stringify 会把I(大写字母I)变成l(小写字母L)。
  • Date.getTime() 的结果总是会慢一个小时。
  • localStorage.getItem 有5%几率返回空字符串。
    在这里插入图片描述
    并且作者发布了这个包到npm上,名叫lodash-utils,一眼看上去,是个非常正常的npm包,跟utils-lodash这个正经的包的名称非常相似。

如果有人误装了lodash-utils这个包并引入,代码表现可能就一团乱麻了,还找不到原因。真是给黑心996公司的小“礼物”了。

现在,这个Github仓库已经被删除了(不过还是可以搜到一些人fork的代码),npm包也已经把它标记为存在安全问题,将代码从npm上移除了。可见npm官方还是很靠谱的,及时下线有风险的代码。
在这里插入图片描述

源码解析

作者是如何做到的呢?我们可以学习一下,但是只单纯学技术,不要作恶噢。要做更多有趣的事情。

立即执行函数

代码整体是一个立即执行函数,

(global => {
   
  
})((0, eval('this')));

该函数的参数是(0, eval('this')),返回值其实就是window,会赋值给函数的参数global

另有朋友反馈说,最新版本是这样的:

(global => {
    
  
})((0, eval)('this'));

该函数的参数是(0, eval)('this'),目的是通过eval在间接调用下默认使用顶层作用域的特性,通过调用this获取顶层对象。这是兼容性最强获取顶层作用域对象的方法,可以兼容浏览器和node,并且在早期版本没有globalThis的情况下也能够很好地支持,甚至在windowglobalThis变量被恶意改写的情况下也可以获取到(类似于使用void 0规避undefined关键词被定义)。

为什么要用立即执行函数?

这样的话,内部定义的变量不会向外暴露。

使用立即执行函数,可以方便的定义局部变量,让其它地方没办法引用该变量。

否则,如果你这样写:

<script>
  const a = 1;
</
  • 15
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hull Qin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值