不管你信不信,面試官讓我使用 JS 計算 LocalStorage 的容量!
Hello,大家好,我是 Sunday。
現在的面試總會遇到很多“奇葩”的問題,不過本著“存在即合理”的態度,從“深入JS”的角度來看,這些個性化的面試題還是挺有意思的。
所以,咱們今天就來看一個“奇葩”面試題:如何使用JS來計算LocalStorage的容量
本文為譯文:https://javascript.plainenglish.io/believe-it-or-not-interviewer-asks-me-to-calculate-localstorage-capacity-using-javascript-12928482e096
01:什么時候需要關注 LocalStorage 空間?
LocalStorage 是瀏覽器提供的一種本地會話存儲的方式,最大支持 5M 的存儲空間。
雖說它的存儲空間是有上限的,但是我相信很多同學都和我一樣,在日常開發中其實并沒有關注過這個問題。畢竟 5M 的默認存儲針對數據而言已經非常大了。
但是,如果你在面對一些足夠復雜的項目,涉及到大量的數據本地存儲且沒有使用 IndexDB 的前提下,那么關注 LocalStorage 存儲空間位置,就變得有意義了。
02:如何計算容量
為了計算總容量,我們將使用 10KB 為單位,相當于 10240 字節。我們將不斷向 LocalStorage 添加 10KB 塊,直到它已滿并引發錯誤。此時,我們統計所有累積的數據,這就是總存儲量!
在 JavaScript 中,字符串使用 UTF-16 編碼存儲。這意味著每個字符通常占用 2 個字節的內存空間。但是,對于某些特殊字符(例如表情符號或某些不太常見的語言字符),它們可能最多使用 4 個字節。
"a".length // 1
"??".length // 2
要估計字符串占用的內存空間(以字節為單位),可以將字符串的長度乘以字符的平均字節大小。對于常規字符集(不包括特殊字符),我們可以這樣估計:
var str = "Hello, World!";
var bytes = str.length * 2; // 2 bytes
console.log(bytes + " bytes"); // 輸出: 26 bytes
要計算以千字節 (KB) 為單位的大小,可以將字節總數除以 1024(1 KB = 1024 字節)
var kb = bytes / 1024;
console.log(kb + " KB"); // 輸出: 0.025 KB
注意:這是一個粗略的估計。由于 JavaScript 引擎的實現、字符串中是否存在特殊字符以及其他因素,實際消耗的內存可能會有所不同。
下面是一段 JavaScript 代碼,可幫助您計算 LocalStorage 的總容量:
// 要制作精確的 10KB 字符串,我們需要一個長度為 5120 個字符的字符串。 UTF-16編碼下,每個字符占用2個字節。因此,5120 個字符等于 10240 個字節,相當于 10KB。
// 然后,它會重復將此字符串添加到 LocalStorage,直到拋出錯誤,表明 LocalStorage 已滿。
const computedTotal = () => {
return new Promise((resolve) => {
let str = "0123456789";
// 首先,我們創建一個10 KB字符串
while (str.length < 5120) {
str += "0123456789";
}
// 清除本地存儲
localStorage.clear();
let temp = str;
// 繼續將10 KB累積到LocalStore中
const timer = setInterval(() => {
try {
localStorage.setItem("temp", temp);
temp += str; // 將另外10 KB添加到臨時字符串
} catch {
// 如果拋出錯誤,這意味著我們已經超出了最大存儲空間
// 考慮每個字符為2字節,以KB為單位計算大小
resolve((temp.length * 2) / 1024);
clearInterval(timer);
// 計算后記得清除LocalStore
localStorage.clear();
}
}, 0);
});
};
(async () => {
const total = await computedTotal();
console.log(`最大容量: ${total}KB`); // 10240KB
})();
圖片
注意:
運行該函數后,我們看到結果是10MB
的字節數,這偏離了眾所周知的 5MB 限制。
根據UTF-16編碼規則,每個字符(chart)要么是2字節,要么是4字節。因此,官網中所說的 5MB,其單位就是字符串的長度。
03:如何計算已使用的容量
要計算已使用的容量,我們需要做的就是迭代 LocalStorage 上的存儲屬性并計算每個存儲屬性的長度。將它們全部加起來就得到了總已用容量!
const computedUse = () => {
let cache = 0;
// 循環訪問LocalStore中的所有 key
for(let key in localStorage) {
// 檢查 key 是否是LocalStore的一部分(而不是其原型)
if (localStorage.hasOwnProperty(key)) {
// 將每個項目的長度添加到總緩存中
cache += localStorage.getItem(key).length * 2; // 每個字符計為2個字節
}
}
// 將總數從字節轉換為千字節并固定為2位小數
return (cache / 1024).toFixed(2);
};
(async () => {
// 創建一個大字符串“o”用于測試目的
let o = '0123456789';
for(let i = 0 ; i < 1000; i++) {
o += '0123456789';
}
// 將大字符串存儲在LocalStore中
localStorage.setItem('o', o);
// 計算使用容量
const useCache = computedUse();
console.log(`計算結果: ${useCache}KB`); // 19.55KB
})();
圖片
04:計算可用容量
在確定了 LocalStorage 的總容量和已用容量后,我們可以通過從總容量中減去已用容量來輕松計算剩余可用容量。
下面是執行此計算的JavaScript 函數:
const computedsurplus = (total, use) => {
return total - use;
};
(async () => {
// 計算Local存儲總容量
const total = await computedTotal();
// 創建一個大字符串“o”用于測試目的
let o = '0123456789';
for(let i = 0 ; i < 1000; i++) {
o += '0123456789';
}
// 將大字符串存儲在LocalStore中
localStorage.setItem('o', o);
// 假設 computedUse 是一個計算已用容量的函數
const useCache = computedUse();
// 計算并記錄剩余可用容量
console.log(`剩余可用容量: ${computedsurplus(total, useCache)}KB`); // 10220.45 KB
})();
圖片