Пять вопросов души
- Какая кодировка символов используется для ключей, хранящихся в localStorage
- Что такое единица измерения 5M?
- Занимает ли ключ localStorage место для хранения?
- Количество ключей в localStorage, влияние на производительность записи и чтения
- Напишите метод для подсчета используемого пространства в localStorage.
Мы отвечаем один за другим, а затем даем каждому интервьюеру еще один вопрос интервью.
我们常说localStorage存储空间是5M,请问这个5M的单位是什么?
Какая кодировка символов используется для ключей и значений, хранящихся в localStorage?
Открытый относительно авторитетный MDNlocalStorage#description
The keys and the values stored with
localStorage
are always in the UTF-16DOMString
format, which uses two bytes per character. As with objects, integer keys are automatically converted to strings.
перевести на китайский:
Ключи и значения, хранящиеся в localStorage, всегда имеют формат UTF-16 DOMString, используя два байта на символ. Как и объекты, целочисленные ключи автоматически преобразуются в строки.
Ответ: UTF-16.
Нет проблем с тем, что здесь описывает MDN, а есть проблемы, потому что UTF-16 использует два байта для каждого символа, есть предпосылки, то есть кодовая точка меньше0xFFFF
(65535), а все, что больше этой кодовой точки, составляет четыре байта.
这是全文的关键。
Что такое единица измерения 5M?
Какова единица измерения 5M?
Опции:
- количество символов
- количество байтов
- значение длины символа
- Номер бита
Не знал, современные браузеры должны быть точнымиВариант 3, длина символов, илиВариант 5, блок кодирования utf-16
Количество символов не равно длине символов, вы должны это знать:
"a".length // 1
"人".length // 1
"𠮷".length // 2
"🔴".length // 2
Современные браузеры обрабатывают строки на основе UTF-16.DOMString
.
Но длина строки 5M явно немного странная.
А по правилам кодировки UTF-16 либо 2 байта, либо четыре байта,所以不如说是 10M 的字节数,更为合理。
当然,2个字节作为一个utf-16的字符编码单元,也可以说是 5M 的utf-16的编码单元。
Давайте сначала напишем метод для подсчета количества байтов в строке utf-16: очень просто, определите, является ли кодовая точка 2 или 4
function sizeofUtf16Bytes(str) {
var total = 0,
charCode,
i,
len;
for (i = 0, len = str.length; i < len; i++) {
charCode = str.charCodeAt(i);
if (charCode <= 0xffff) {
total += 2;
} else {
total += 4;
}
}
return total;
}
Давайте хранить до 10M байт
В качестве ключа оставляем 8 байтов, 8 байтов могут быть 4 символами, или 3 символами, кодовая точка которых больше 65535, или комбинацией.
Возможны следующие три комбинации:
aaaa
aa🔴
🔴🔴
Если на этой основе будет добавлен какой-либо символ, будет сообщено об исключении ошибки.
const charTxt = "人";
let count = (10 * 1024 * 1024 / 2) - 8 / 2;
let content = new Array(count).fill(charTxt).join("");
const key = "aa🔴";
localStorage.clear();
try {
localStorage.setItem(key, content);
} catch (err) {
console.log("err", err);
}
const sizeKey = sizeofUtf16Bytes(key);
const contentSize = sizeofUtf16Bytes(content);
console.log("key size:", sizeKey, content.length);
console.log("content size:", contentSize, content.length);
console.log("total size:", sizeKey + contentSize, content.length + key.length);
В случае современных браузеров:
Поэтому точнее и проще понять, что это количество байтов 10M.
Если вы говорите 5M, то его единицей является длина строки, а не количество символов.
Ответ: значение длины строки или единица кода utf-16.
更合理的答案是 10M字节空间。
Занимает ли ключ localStorage место для хранения?
Мы устанавливаем key и val на длину 2,5M соответственно.
const charTxt = "a";
let count = (2.5 * 1024 * 1024);
let content = new Array(count).fill(charTxt).join("");
const key = new Array(count).fill(charTxt).join("");
localStorage.clear();
try {
console.time("setItem")
localStorage.setItem(key, content);
console.timeEnd("setItem")
} catch (err) {
console.log("err code:", err.code);
console.log("err message:", err.message)
}
Выполнить нормально.
Добавляем длину контента1
, становится2.5 M + 1
, длина ключа по-прежнему2.5M
длина
const charTxt = "a";
let count = (2.5 * 1024 * 1024);
let content = new Array(count).fill(charTxt).join("") + 1;
const key = new Array(count).fill(charTxt).join("");
localStorage.clear();
try {
console.time("setItem")
localStorage.setItem(key, content);
console.timeEnd("setItem")
} catch (err) {
console.log("err code:", err.code);
console.log("err message:", err.message)
}
Возникло исключение, и хранилище не удалось. Дополнительные сведения об исключении см.обнаружение localstorage_feature:
function storageAvailable(type) {
var storage;
try {
storage = window[type];
var x = '__storage_test__';
storage.setItem(x, x);
storage.removeItem(x);
return true;
}
catch(e) {
return e instanceof DOMException && (
// everything except Firefox
e.code === 22 ||
// Firefox
e.code === 1014 ||
// test name field too, because code might not be present
// everything except Firefox
e.name === 'QuotaExceededError' ||
// Firefox
e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
// acknowledge QuotaExceededError only if there's something already stored
(storage && storage.length !== 0);
}
}
Ответ: занимать место
Количество ключей, влияние на чтение и запись
нас500 * 1000
ключ, как показано ниже
let keyCount = 500 * 1000;
localStorage.clear();
for (let i = 0; i < keyCount; i++) {
localStorage.setItem(i, "");
}
setTimeout(() => {
console.time("save_cost");
localStorage.setItem("a", "1");
console.timeEnd("save_cost");
}, 2000)
setTimeout(() => {
console.time("read_cost");
localStorage.getItem("a");
console.timeEnd("read_cost");
}, 2000)
// save_cost: 0.05615234375 ms
// read_cost: 0.008056640625 ms
Вы выполняете только код сохранения:
localStorage.clear();
console.time("save_cost");
localStorage.setItem("a", "1");
console.timeEnd("save_cost");
// save_cost: 0.033203125 ms
Его можно тестировать несколько раз, и влияние, безусловно, есть, но только несколько раз, не особенно большое.
И наоборот, что, если таблица хранимых значений больше?
const charTxt = "a";
const count = 5 * 1024 * 1024 - 1
const val1 = new Array(count).fill(charTxt).join("");
setTimeout(() =>{
localStorage.clear();
console.time("save_cost_1");
localStorage.setItem("a", val1);
console.timeEnd("save_cost_1");
},1000)
setTimeout(() =>{
localStorage.clear();
console.time("save_cost_2");
localStorage.setItem("a", "a");
console.timeEnd("save_cost_2");
},1000)
// save_cost_1: 12.276123046875 ms
// save_cost_2: 0.010009765625 ms
Это может быть проверено много раз Размер одного значения имеет большое влияние на производительность памяти, и то же самое верно для чтения, что разумно.
Поэтому старайтесь не сохранять большие значения, потому что это синхронное чтение, чистые большие данные, просто используйте indexedDB.
Ответ: Количество ключей влияет на скорость чтения, но не сильно. Размер значения больше влияет на производительность, поэтому не рекомендуется сохранять большие данные.
Напишите метод для подсчета используемого пространства в localStorage.
Маленькая версия для современных браузеров:
function sieOfLS() {
return Object.entries(localStorage).map(v => v.join('')).join('').length;
}
Тестовый код:
localStorage.clear();
localStorage.setItem("🔴", 1);
localStorage.setItem("🔴🔴🔴🔴🔴🔴🔴🔴", 1111);
console.log("size:", sieOfLS()) // 23
// 🔴*9 + 1 *5 = 2*9 + 1*5 = 23
стандарт протокола html
Технической рабочей группы WHATWG по гипертекстовым приложениямlocalstorageПротокол определяет методы, свойства и т. д. localStorage, но не определяет четко его пространство для хранения. Это приводит к различным максимальным ограничениям для каждого браузера.
Это не стандарт ES.
кодировка страницы utf-8
Наши html-страницы часто появляются <meta charset="UTF-8">
.
Сообщите браузеру, к какому формату кодировки символов принадлежит эта страница, и браузер выполнит декодирование на следующем шаге.
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>容器</title>
</head>
Это не имеет ничего общего с хранилищем localStorage.
расширение локального хранилища
Пространство localStorage составляет 10M байт, чего обычно достаточно, но у людей всегда есть жадность. Действительно достигнут лимит места, что делать?
Расширение LocalStorage — это отдельная тема.
напиши в конце
Не забывайте о первоначальном намерении, получайте то, что получаете, и не уставайте. Если вы считаете, что это хорошо, ваши лайки и комментарии - самая большая мотивация для меня двигаться вперед.
**Группа технического обмена, пожалуйста, перейдите наиди сюда. Или добавьте мое облако похорон WeChat и учитесь вместе.