幾個常見面試題,工作中也經(jīng)常用到
?
01 什么是防抖和節(jié)流,他們的應(yīng)用場景有哪些
?在 Issue 中交流與討論: 01 什么是防抖和節(jié)流,他們的應(yīng)用場景有哪些[1]
?
防抖 (debounce)
防抖,顧名思義,防止抖動,以免把一次事件誤認(rèn)為多次,敲鍵盤就是一個每天都會接觸到的防抖操作。
想要了解一個概念,必先了解概念所應(yīng)用的場景。在 JS 這個世界中,有哪些防抖的場景呢
- 登錄、發(fā)短信等按鈕避免用戶點擊太快,以致于發(fā)送了多次請求,需要防抖
- 調(diào)整瀏覽器窗口大小時,resize 次數(shù)過于頻繁,造成計算過多,此時需要一次到位,就用到了防抖
- 文本編輯器實時保存,當(dāng)無任何更改操作一秒后進(jìn)行保存
代碼如下,可以看出來「防抖重在清零?clearTimeout(timer)」
function?debounce?(f,?wait)?{
??let?timer
??return?(...args)?=>?{
????clearTimeout(timer)
????timer?=?setTimeout(()?=>?{
??????f(...args)
????},?wait)
??}
}
節(jié)流 (throttle)
節(jié)流,顧名思義,控制水的流量。控制事件發(fā)生的頻率,如控制為 1s 發(fā)生一次,甚至 1 分鐘發(fā)生一次。與服務(wù)端(server)及網(wǎng)關(guān)(gateway)控制的限流 (Rate Limit) 類似。
scroll?事件,每隔一秒計算一次位置信息等- 瀏覽器播放事件,每個一秒計算一次進(jìn)度信息等
- input 框?qū)崟r搜索并發(fā)送請求展示下拉列表,每隔一秒發(fā)送一次請求 (也可做防抖)
代碼如下,可以看出來「節(jié)流重在加鎖?timer=timeout」
function?throttle?(f,?wait)?{
??let?timer
??return?(...args)?=>?{
????if?(timer)?{?return?}
????timer?=?setTimeout(()?=>?{
??????f(...args)
??????timer?=?null
????},?wait)
??}
}
總結(jié) (簡要答案)
- 防抖:防止抖動,單位時間內(nèi)事件觸發(fā)會被重置,避免事件被誤傷觸發(fā)多次。「代碼實現(xiàn)重在清零?
clearTimeout」。防抖可以比作等電梯,只要有一個人進(jìn)來,就需要再等一會兒。業(yè)務(wù)場景有避免登錄按鈕多次點擊的重復(fù)提交。 - 節(jié)流:控制流量,單位時間內(nèi)事件只能觸發(fā)一次,與服務(wù)器端的限流 (Rate Limit) 類似。「代碼實現(xiàn)重在開鎖關(guān)鎖?
timer=timeout; timer=null」。節(jié)流可以比作過紅綠燈,每等一個紅燈時間就可以過一批。
02 在前端開發(fā)中,如何獲取瀏覽器的唯一標(biāo)識
??更多描述: 如何獲取瀏覽器的唯一標(biāo)識,原理是什么??
?在 Issue 中交流與討論: 02 在前端開發(fā)中,如何獲取瀏覽器的唯一標(biāo)識[2]
?
由于不同的系統(tǒng)顯卡繪制?canvas?時渲染參數(shù)、抗鋸齒等算法不同,因此繪制成圖片數(shù)據(jù)的?CRC?校驗也不一樣。
function?getCanvasFp?()?{
??const?canvas?=?document.getElementById('canvas')
??const?ctx?=?canvas.getContext('2d')
??ctx.font?=?'14px?Arial'
??ctx.fillStyle?=?'#ccc'
??ctx.fillText('hello,?shanyue',?2,?2)
??return?canvas.toDataURL('image/jpeg')
}
因此根據(jù)?canvas?可以獲取瀏覽器指紋信息。
- 繪制?
canvas,獲取?base64?的 dataurl - 對 dataurl 這個字符串進(jìn)行?
md5?摘要計算,得到指紋信息
但是對于常見的需求就有成熟的解決方案,若在生產(chǎn)環(huán)境使用,可以使用以下庫
- fingerprintjs2[3]
它依據(jù)以下信息,獲取到瀏覽器指紋信息,「而這些信息,則成為?component」
canvaswebglUserAgentAudioContext- 對新式 API 的支持程度等
requestIdleCallback(function?()?{
??Fingerprint2.get((components)?=>?{
????const?values?=?components.map((component)?=>?component.value)
????const?fp?=?Fingerprint2.x64hash128(values.join(''),?31)
??})
})
在?fingerprintjs2?中,對于?component?也有分類
- browser independent component[4]:有些?
component?同一設(shè)備跨瀏覽器也可以得到相同的值,有些獨(dú)立瀏覽器,得到不同的值 - stable component[5]: 有些?
component?刷新后值就會發(fā)生變化,稱為不穩(wěn)定組件
在實際業(yè)務(wù)中,可根據(jù)業(yè)務(wù)選擇合適的組件
const?options?=?{
??excludes:?{userAgent:?true,?language:?true}
}
簡答
根據(jù)?canvas?可以獲取瀏覽器指紋信息
- 繪制?
canvas,獲取?base64?的 dataurl - 對 dataurl 這個字符串進(jìn)行?
md5?摘要計算,得到指紋信息
若在生產(chǎn)環(huán)境使用,可以使用 fingerprintjs2[6],根據(jù)業(yè)務(wù)需求,如單設(shè)備是否可跨瀏覽器,以此選擇合適的?component
03 在服務(wù)端應(yīng)用中如何獲得客戶端 IP
?在 Issue 中交流與討論: 03 在服務(wù)端應(yīng)用中如何獲得客戶端 IP[7]
?
「如果有?x-forwarded-for?的請求頭,則取其中的第一個 IP,否則取建立連接 socket 的 remoteAddr。」
而?x-forwarded-for?基本已成為了基于 proxy 的標(biāo)準(zhǔn) HTTP 頭,格式如下,可見第一個 IP 代表其真實的 IP,可以參考 MDN X-Forwarded-For[8]
X-Forwarded-For:?203.0.113.195,?70.41.3.18,?150.172.238.178
X-Forwarded-For:?,?,?
以下是?koa?獲取 IP 的方法
??get?ips()?{
????const?proxy?=?this.app.proxy;
????const?val?=?this.get(this.app.proxyIpHeader);
????let?ips?=?proxy?&&?val
????????val.split(/\s*,\s*/)
??????:?[];
????if?(this.app.maxIpsCount?>?0)?{
??????ips?=?ips.slice(-this.app.maxIpsCount);
????}
????return?ips;
??},
??get?ip()?{
????if?(!this[IP])?{
??????this[IP]?=?this.ips[0]?||?this.socket.remoteAddress?||?'';
????}
????return?this[IP];
??},
參見源碼: https://github.com/koajs/koa/blob/master/lib/request.js#L433
04 js 如何全部替代一個子串為另一個子串
??更多描述: 假設(shè)有一個字符串 `hello. hello. hello. ` 需要替換為 `AAA`,即把 `hello. ` 替換為 `A`??
?在 Issue 中交流與討論: 04 js 如何全部替代一個子串為另一個子串[9]
?
如果需要全量替換字符串,可以使用?String.prototype.replace(re, replacer),其中正則表達(dá)式需要開啟?global?flag
const?s?=?'foo?foo?foo'
s.replce(/foo/g,?'bar')
那如題中,「是否可以使用正則表達(dá)式來替代子串」
答:「不可以,因為使用子串構(gòu)建正則時,有可能有特殊字符,就有可能出現(xiàn)問題」,如下
//?期待結(jié)果:?'AhelloX?hello3?'
>?'hello.?helloX?hello3?'.replace(new?RegExp('hello.?',?'g'),?'A')
"AAA"
而在?javascript?中替換子串只能使用一種巧妙的辦法:str.split('foo').join('bar')
>?'hello.?hello.?hello.?'.split('hello.?').join('A')
"AAA"
真是一個巧(笨)妙(拙)的辦法啊!!!!!「大概 TC39 也意識到了一個問題,于是出了一個新的 API」,在?ESNext?中
String.prototype.replaceAll()
'aabbcc'.replaceAll('b',?'.');
//?'aa..cc'
詳細(xì)文檔在 String.prototype.replaceAll[10]
總結(jié)(及直接答案)
兩種辦法
str.split('foo').join('bar')str.replaceAll('foo', 'bar'),在?ESNext?中,目前支持性不好
05 如何獲取一個進(jìn)程的內(nèi)存并監(jiān)控
??更多描述: 在編寫腳本時,有時會出現(xiàn)內(nèi)存過大發(fā)生 OOM 的事情,那我們?nèi)绾蔚弥硞€進(jìn)程的內(nèi)存?另外又如何監(jiān)控它??
?在 Issue 中交流與討論: 05 如何獲取一個進(jìn)程的內(nèi)存并監(jiān)控[11]
?
通過?ps?可以獲知一個進(jìn)程所占用的內(nèi)存
$?ps?-O?rss?-p?3506
??PID???RSS?S?TTY??????????TIME?COMMAND
?3506??6984?S?pts/1????00:00:00?vim
如果要監(jiān)控內(nèi)存,肯定使用對進(jìn)程萬能的命令?pidstat?(PS: 這名字一聽就知道是干嘛的)
##?-r?顯示內(nèi)存信息
##?-p?指定?pid
##?1:?每個一秒打印一次
$?pidstat?-r?-p?3506?1
Linux?3.10.0-957.21.3.el7.x86_64?(shanyue)??????11/04/19????????_x86_64_????????(2?CPU)
20:47:35??????UID???????PID??minflt/s??majflt/s?????VSZ????RSS???%MEM??Command
20:47:36????????0??????3506??????0.00??????0.00??139940???6984???0.18??vim
20:47:37????????0??????3506??????0.00??????0.00??139940???6984???0.18??vim
20:47:38????????0??????3506??????0.00??????0.00??139940???6984???0.18??vim
20:47:39????????0??????3506??????0.00??????0.00??139940???6984???0.18??vim
20:47:40????????0??????3506??????0.00??????0.00??139940???6984???0.18??vim
20:47:41????????0??????3506??????0.00??????0.00??139940???6984???0.18??vim
pidstat?是屬于?sysstat?下的 linux 性能工具,但在 mac 中,如何定位內(nèi)存的變化?此時可以使用萬能的?top/htop
$?htop?-p?31796總結(jié)
簡而言之,有以下三個命令
pidstat -rhtop/top -pps -O rss -p
關(guān)于更多指標(biāo)的監(jiān)控可以參考我的文章: linux 各項監(jiān)控指標(biāo)小記[12]
06 CORS 如果需要指定多個域名怎么辦
?在 Issue 中交流與討論: 06 CORS 如果需要指定多個域名怎么辦[13]
?
CORS?通過控制?Access-Control-Allow-Origin?控制哪些域名可以共享資源,取值如下
Access-Control-Allow-Origin:??|?*
其中?*?代表所有域名,origin?代表指定特定域名,那如何設(shè)置多個域名了?
此時需要通過代碼實現(xiàn),「根據(jù)請求頭中的?Origin?來設(shè)置響應(yīng)頭?Access-Control-Allow-Origin」,那 Origin 又是什么東西?
請求頭: Origin
并不是所有請求都會自動帶上?Origin,在瀏覽器中帶?Origin?的邏輯如下
- 如果存在跨域,則帶上?
Origin,值為當(dāng)前域名 - 如果不存在跨域,則不帶?
Origin
邏輯理清楚后,關(guān)于服務(wù)器中對于?Access-Control-Allow-Origin?設(shè)置多域名的邏輯也很清晰了
- 如果請求頭不帶有?
Origin,證明未跨域,則不作任何處理 - 如果請求頭帶有?
Origin,證明跨域,根據(jù)?Origin?設(shè)置相應(yīng)的?Access-Control-Allow-Origin:
使用偽代碼實現(xiàn)如下:
//?獲取?Origin?請求頭
const?requestOrigin?=?ctx.get('Origin');
//?如果沒有,則跳過
if?(!requestOrigin)?{
??return?await?next();
}
//?設(shè)置響應(yīng)頭
ctx.set('Access-Control-Allow-Origin',?requestOrigin)
Vary: Origin
此時可以給多個域名控制 CORS,但此時假設(shè)有兩個域名訪問?static.shanyue.tech?的跨域資源
foo.shanyue.tech,響應(yīng)頭中返回?Access-Control-Allow-Origin: foo.shanyue.techbar.shanyue.tech,響應(yīng)頭中返回?Access-Control-Allow-Origin: bar.shanyue.tech
看起來一切正常,但如果中間有緩存怎么辦?
foo.shanyue.tech,響應(yīng)頭中返回?Access-Control-Allow-Origin: foo.shanyue.tech,被 CDN 緩存- 「
bar.shanyue.tech,因由緩存,響應(yīng)頭中返回?Access-Control-Allow-Origin: foo.shanyue.tech,跨域出現(xiàn)問題」
此時,Vary: Origin?就上場了,代表為不同的?Origin?緩存不同的資源
總結(jié) (簡要答案)
CORS 如何指定多個域名?
「根據(jù)請求頭中的?Origin?來設(shè)置響應(yīng)頭?Access-Control-Allow-Origin」,思路如下
- 總是設(shè)置?
Vary: Origin,避免 CDN 緩存破壞 CORS 配置 - 如果請求頭不帶有?
Origin,證明未跨域,則不作任何處理 - 如果請求頭帶有?
Origin,證明瀏覽器訪問跨域,根據(jù)?Origin?設(shè)置相應(yīng)的?Access-Control-Allow-Origin:
使用偽代碼實現(xiàn)如下
//?獲取?Origin?請求頭
const?requestOrigin?=?ctx.get('Origin');
ctx.set('Vary',?'Origin')
//?如果沒有,則跳過
if?(!requestOrigin)?{
??return?await?next();
}
//?設(shè)置響應(yīng)頭
ctx.set('Access-Control-Allow-Origin',?requestOrigin)
?相關(guān)問題:如何避免 CDN 為 PC 端緩存移動端頁面[14]
?
07 既然 cors 配置可以做跨域控制,那可以防止 CSRF 攻擊嗎
?在 Issue 中交流與討論: 07 既然 cors 配置可以做跨域控制,那可以防止 CSRF 攻擊嗎?[15]
?
「對 CORS 一點用也沒有」
- 「
form?提交不通過?CORS?檢測」,你可以在本地進(jìn)行測試 - 即使通過?
xhr?及?fetch?進(jìn)行提交被 CORS 攔住,「但是對于簡單請求而言,請求仍被發(fā)送」,已造成了攻擊
08 如何避免 CDN 為 PC 端緩存移動端頁面
?在 Issue 中交流與討論: 08 如何避免 CDN 為 PC 端緩存移動端頁面[16]
?
如果 PC 端和移動端是一套代碼則不會出現(xiàn)這個問題。「這個問題出現(xiàn)在 PC 端和移動端是兩套代碼,卻共用一個域名。」
使用?nginx?配置如下,根據(jù) UA 判斷是否移動端,而走不同的邏輯 (判斷 UA 是否移動端容易出問題)
location / {
// 默認(rèn) PC 端
root /usr/local/website/web;
# 判斷 UA,訪問移動端
if ( $http_user_agent ~* "(Android|webOS|iPhone|iPad|BlackBerry)" ){
root /usr/local/website/mobile;
}
index index.html index.htm;
}
解決方案通常使用?Vary?響應(yīng)頭,來控制 CDN 對不同請求頭的緩存。
「此處可以使用?Vary: User-Agent?,代表如果 User-Agent 不一樣,則重新發(fā)起請求,而非從緩存中讀取頁面」
Vary: User-Agent
當(dāng)然,User-Agent?實在過多,此時緩存失效就會過多。
簡答
使用?Vary: User-Agent,根據(jù) UA 進(jìn)行緩存。
Vary: User-Agent
但最好不要出現(xiàn)這種情況,PC 端和移動端如果是兩套代碼,建議用兩個域名,理由如下
nginx?判斷是否移動端容易出錯- 對緩存不友好
09 如何實現(xiàn)表格單雙行條紋樣式
?在 Issue 中交流與討論: 09 如何實現(xiàn)表格單雙行條紋樣式[17]
?
通過?css3?中偽類?:nth-child?來實現(xiàn)。其中?:nth-child(an+b)?匹配下標(biāo)?{ an + b; n = 0, 1, 2, ...}?且結(jié)果為整數(shù)的子元素
nth-child(2n)/nth-child(even): 雙行樣式nth-child(2n+1)/nth-child(odd): 單行樣式
其中?tr?在表格中代表行,實現(xiàn)表格中單雙行樣式就很簡單了:
tr:nth-child(2n)?{
??background-color:?red;
}
tr:nth-child(2n+1)?{
??background-color:?blue;
}
同理:
- 如何匹配最前三個子元素:?
:nth-child(-n+3) - 如何匹配最后三個子元素:?
:nth-last-child(-n+3)
10 簡述下 css specificity
?在 Issue 中交流與討論: 10 簡述下 css specificity[18]
?
css specificity?即 css 中關(guān)于選擇器的權(quán)重,以下三種類型的選擇器依次下降
id?選擇器,如?#appclass、attribute?與?pseudo-classes?選擇器,如?.header、[type="radio"]與?:hovertype?標(biāo)簽選擇器和偽元素選擇器,如?h1、p?和?::before
其中通配符選擇器?*,組合選擇器?+ ~ >,否定偽類選擇器?:not()?對優(yōu)先級無影響
另有內(nèi)聯(lián)樣式??及?!important(最高) 具有更高的權(quán)重
?`:not` 的優(yōu)先級影響 - codepen[19]?可以看出?
?:not?對選擇器的優(yōu)先級無任何影響
11 node 中 module.exports 與 exports 有什么區(qū)別
?在 Issue 中交流與討論: 11 node 中 module.exports 與 exports 有什么區(qū)別[20]
?
「一句話:exports?是?module.exports?的引用,如果?exports?沒有重賦值,則二者沒有任何區(qū)別」
類似如下所示
const?exports?=?module.exports
那如下結(jié)果會如何導(dǎo)出?
module.exports?=?100
exports?=?3
很顯然會導(dǎo)出 100,畢竟?exports?進(jìn)行了重賦值。
「那在 node 源碼中如何實現(xiàn)的呢?」?從源碼里可以看出?「exports」?的實質(zhì)
module wrapper詳見源碼: https://github.com/nodejs/node/blob/master/lib/internal/modules/cjs/loader.js#L1252,可以看出符合猜想
眾所周知,node 中所有的模塊代碼都被包裹在這個函數(shù)中
(function(exports,?require,?module,?__filename,?__dirname)?{
??exports.a?=?3
});
而以下源碼指出,exports?是如何得來
const?dirname?=?path.dirname(filename);
const?require?=?makeRequireFunction(this,?redirects);
let?result;
//?從這里可以看出來?exports?的實質(zhì)
const?exports?=?this.exports;
const?thisValue?=?exports;
const?module?=?this;
if?(requireDepth?===?0)?statCache?=?new?Map();
if?(inspectorWrapper)?{
??result?=?inspectorWrapper(compiledWrapper,?thisValue,?exports,
????????????????????????????require,?module,?filename,?dirname);
}?else?{
??//?這里是模塊包裝函數(shù)
??result?=?compiledWrapper.call(thisValue,?exports,?require,?module,
????????????????????????????????filename,?dirname);
}
12 如何獲取當(dāng)前系統(tǒng)中的在線用戶數(shù) (并發(fā)用戶數(shù))
??更多描述: 一些 SaaS 系統(tǒng)基于 Pricing 的考慮,會限制團(tuán)隊人數(shù)及同時在線數(shù),如何實現(xiàn)??
?在 Issue 中交流與討論: 12 如何獲取當(dāng)前系統(tǒng)中的在線用戶數(shù) (并發(fā)用戶數(shù))[21]
?
?一些 SaaS 系統(tǒng)基于定價策略的考慮,會限制團(tuán)隊人數(shù)及同時在線數(shù),如何實現(xiàn)?
?
通過?redis?的?zset?可實現(xiàn)并發(fā)用戶數(shù)。
當(dāng)一個用戶請求任何接口時,實現(xiàn)一個 middleware,處理以下邏輯
//?當(dāng)一個用戶訪問任何接口時,對該用戶Id,寫入?zset
await?redis.zadd(`Organization:${organizationId}:concurrent`,?Date.now(),?`User:${userId}`)
//?查詢當(dāng)前機(jī)構(gòu)的并發(fā)數(shù)
//?通過查詢一分鐘內(nèi)的活躍用戶來確認(rèn)并發(fā)數(shù),如果超過則拋出特定異常
const?activeUsers?=?await?redis.zrangebyscore(`Organization:${organizationId}:concurrent`,?Date.now()?-?1000?*?60,?Date.now())
//?查出并發(fā)數(shù)
const?count?=?activeUsers.length
//?刪掉過期的用戶
await?redis.zrembyscore(`Organization:${organizationId}:concurrent`,?Date.now()?-?1000?*?60,?Date.now())
總結(jié)
- 每當(dāng)用戶訪問服務(wù)時,把該用戶的 ID 寫入優(yōu)先級隊列,權(quán)重為當(dāng)前時間
- 根據(jù)權(quán)重(即時間)計算一分鐘內(nèi)該機(jī)構(gòu)的用戶數(shù)
- 刪掉一分鐘以上過期的用戶
13 如何把 json 數(shù)據(jù)轉(zhuǎn)化為 demo.json 并下載文件
?在 Issue 中交流與討論: 13 如何把 json 數(shù)據(jù)轉(zhuǎn)化為 demo.json 并下載文件[22]
?
json 視為字符串,可以利用?DataURL?進(jìn)行下載
Text -> DataURL
除了使用 DataURL,還可以轉(zhuǎn)化為 Object URL 進(jìn)行下載
Text -> Blob -> Object URL
可以把以下代碼直接粘貼到控制臺下載文件
function?download?(url,?name)?{
??const?a?=?document.createElement('a')
??a.download?=?name
??a.rel?=?'noopener'
??a.href?=?url
??//?觸發(fā)模擬點擊
??a.dispatchEvent(new?MouseEvent('click'))
??//?或者?a.click()
}
const?json?=?{
??a:?3,
??b:?4,
??c:?5
}
const?str?=?JSON.stringify(json,?null,?2)
//?方案一:Text -> DataURL
const?dataUrl?=?`data:,${str}`
download(dataUrl,?'demo.json')
//?方案二:Text -> Blob -> ObjectURL
const?url?=?URL.createObjectURL(new?Blob(str.split('')))
download(url,?'demo1.json')
總結(jié)
- 模擬下載,可以通過新建一個?
?標(biāo)簽并設(shè)置?url?及?download?屬性來下載 - 可以通過把?
json?轉(zhuǎn)化為?dataurl?來構(gòu)造 URL - 可以通過把?
json?轉(zhuǎn)換為?Blob?再轉(zhuǎn)化為?ObjectURL?來構(gòu)造 URL
14 在瀏覽器中如何監(jiān)聽剪切板中內(nèi)容
?在 Issue 中交流與討論: 14 在瀏覽器中如何監(jiān)聽剪切板中內(nèi)容[23]
?
通過?Clipboard API?可以獲取剪切板中內(nèi)容,但需要獲取到?clipboard-read?的權(quán)限,以下是關(guān)于讀取剪貼板內(nèi)容的代碼:
//?是否能夠有讀取剪貼板的權(quán)限
//?result.state?==?"granted"?||?result.state?==?"prompt"
const?result?=?await?navigator.permissions.query({?name:?"clipboard-read"?})
//?獲取剪貼板內(nèi)容
const?text?=?await?navigator.clipboard.readText()
?注: 該方法在?
?devtools?中不生效
01 什么是防抖和節(jié)流,他們的應(yīng)用場景有哪些:?https://github.com/shfshanyue/Daily-Question/issues/3
[2]02 在前端開發(fā)中,如何獲取瀏覽器的唯一標(biāo)識:?https://github.com/shfshanyue/Daily-Question/issues/28
[3]fingerprintjs2:?https://github.com/Valve/fingerprintjs2
[4]browser independent component:?https://github.com/Valve/fingerprintjs2/wiki/Browser-independent-components
[5]stable component:?https://github.com/Valve/fingerprintjs2/wiki/Stable-components
[6]fingerprintjs2:?https://github.com/Valve/fingerprintjs2
[7]03 在服務(wù)端應(yīng)用中如何獲得客戶端 IP:?https://github.com/shfshanyue/Daily-Question/issues/288
[8]X-Forwarded-For:?https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For
[9]04 js 如何全部替代一個子串為另一個子串:?https://github.com/shfshanyue/Daily-Question/issues/361
[10]String.prototype.replaceAll:?https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll
[11]05 如何獲取一個進(jìn)程的內(nèi)存并監(jiān)控:?https://github.com/shfshanyue/Daily-Question/issues/4
[12]linux 各項監(jiān)控指標(biāo)小記:?https://shanyue.tech/op/linux-monitor.html
[13]06 CORS 如果需要指定多個域名怎么辦:?https://github.com/shfshanyue/Daily-Question/issues/364
[14]如何避免 CDN 為 PC 端緩存移動端頁面:?https://github.com/shfshanyue/Daily-Question/issues/330
[15]07 既然 cors 配置可以做跨域控制,那可以防止 CSRF 攻擊嗎 :?https://github.com/shfshanyue/Daily-Question/issues/366
[16]08 如何避免 CDN 為 PC 端緩存移動端頁面:?https://github.com/shfshanyue/Daily-Question/issues/330
[17]09 如何實現(xiàn)表格單雙行條紋樣式:?https://github.com/shfshanyue/Daily-Question/issues/309
[18]10 簡述下 css specificity:?https://github.com/shfshanyue/Daily-Question/issues/311
[19]:not?的優(yōu)先級影響 - codepen:?https://codepen.io/shanyue/pen/dyGQqBe
11 node 中 module.exports 與 exports 有什么區(qū)別:?https://github.com/shfshanyue/Daily-Question/issues/351
[21]12 如何獲取當(dāng)前系統(tǒng)中的在線用戶數(shù) (并發(fā)用戶數(shù)):?https://github.com/shfshanyue/Daily-Question/issues/368
[22]13 如何把 json 數(shù)據(jù)轉(zhuǎn)化為 demo.json 并下載文件:?https://github.com/shfshanyue/Daily-Question/issues/352
[23]14 在瀏覽器中如何監(jiān)聽剪切板中內(nèi)容:?https://github.com/shfshanyue/Daily-Question/issues/315
[24]【Q019】如何實現(xiàn)選中復(fù)制的功能:?https://github.com/shfshanyue/Daily-Question/issues/20
