<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          localStorage靈魂五問(wèn). 5M空間?? 10M !!!

          共 1142字,需瀏覽 3分鐘

           ·

          2021-11-16 19:37

          靈魂五問(wèn)

          1. localStorage 存儲(chǔ)的鍵值采用什么字符編碼
          2. 5M 的單位是什么
          3. localStorage 鍵占不占存儲(chǔ)空間
          4. localStorage的鍵的數(shù)量,對(duì)寫和讀性能的影響
          5. 寫個(gè)方法統(tǒng)計(jì)一個(gè)localStorage已使用空間

          我們挨個(gè)解答,之后給各位面試官又多了一個(gè)面試題。

          我們常說(shuō)localStorage存儲(chǔ)空間是5M,請(qǐng)問(wèn)這個(gè)5M的單位是什么?

          localStorage ?存儲(chǔ)的鍵值采用什么字符編碼?

          打開相對(duì)權(quán)威的MDN localStorage#description[1]

          The keys and the values stored with?localStorage?are?always?in the UTF-16?`DOMString`[2]?format, which uses two bytes per character. As with objects, integer keys are automatically converted to strings.

          翻譯成中文:

          localStorage 存儲(chǔ)的鍵和值始終采用 UTF-16 DOMString 格式,每個(gè)字符使用兩個(gè)字節(jié)。與對(duì)象一樣,整數(shù)鍵將自動(dòng)轉(zhuǎn)換為字符串。

          答案:UTF-16

          MDN這里描述的沒有問(wèn)題,也有問(wèn)題,因?yàn)閁TF-16,每個(gè)字符使用兩個(gè)字節(jié),是有前提條件的,就是碼點(diǎn)小于0xFFFF(65535), 大于這個(gè)碼點(diǎn)的是四個(gè)字節(jié)。

          這是全文的關(guān)鍵。

          5M 的單位是什么

          5M的單位是什么?

          選項(xiàng):

          1. 字符的個(gè)數(shù)
          2. 字節(jié)數(shù)
          3. 字符的長(zhǎng)度值
          4. bit 數(shù)
          5. utf-16編碼單元

          以前不知道,現(xiàn)代瀏覽器,準(zhǔn)確的應(yīng)該是 選項(xiàng)3,字符的長(zhǎng)度 ,亦或 選項(xiàng)5, utf-16編碼單元

          字符的個(gè)數(shù),并不等于字符的長(zhǎng)度,這一點(diǎn)要知道:

          "a".length?//?1
          "人".length?//?1
          "??".length?//?2
          "??".length?//?2

          現(xiàn)代瀏覽器對(duì)字符串的處理是基于UTF-16?`DOMString`[3]。

          但是說(shuō)5M字符串的長(zhǎng)度,顯然有那么點(diǎn)怪異。

          而根據(jù) UTF-16編碼規(guī)則,要么2個(gè)字節(jié),要么四個(gè)字節(jié),所以不如說(shuō)是 10M 的字節(jié)數(shù),更為合理。

          當(dāng)然,2個(gè)字節(jié)作為一個(gè)utf-16的字符編碼單元,也可以說(shuō)是 5M 的utf-16的編碼單元。

          我們先編寫一個(gè)utf-16字符串計(jì)算字節(jié)數(shù)的方法:非常簡(jiǎn)單,判斷碼點(diǎn)決定是2還是4

          function?sizeofUtf16Bytes(str)?{
          ????var?total?=?0,
          ????????charCode,
          ????????i,
          ????????len;
          ????for?(i?=?0,?len?=?str.length;?i?????????charCode?=?str.charCodeAt(i);
          ????????if?(charCode?<=?0xffff)?{
          ????????????total?+=?2;
          ????????}?else?{
          ????????????total?+=?4;
          ????????}
          ????}
          ????return?total;
          }

          我們?cè)俑^10M的字節(jié)數(shù)來(lái)存儲(chǔ)

          我們留下8個(gè)字節(jié)數(shù)作為key,8個(gè)字節(jié)可是普通的4個(gè)字符換,也可是碼點(diǎn)大于65535的3個(gè)字符,也可是是組合。

          下面的三個(gè)組合,都是可以的,

          1. aaaa
          2. aa??
          3. ????

          在此基礎(chǔ)上增加任意一個(gè)字符,都會(huì)報(bào)錯(cuò)異常異常。

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

          現(xiàn)代瀏覽器的情況下:

          所以,說(shuō)是10M的字節(jié)數(shù),更為準(zhǔn)確,也更容易讓人理解。

          如果說(shuō)5M,那其單位就是字符串的長(zhǎng)度,而不是字符數(shù)。

          答案:字符串的長(zhǎng)度值, 或者utf-16的編碼單元

          更合理的答案是 10M字節(jié)空間。

          localStorage 鍵占不占存儲(chǔ)空間

          我們把 key和val各自設(shè)置長(zhǎng) 2.5M的長(zhǎng)度

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

          執(zhí)行正常。

          我們把content的長(zhǎng)度加1, 變?yōu)?2.5 M + 1, key的長(zhǎng)度依舊是 2.5M的長(zhǎng)度

          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)
          }
          d0f362969d60fb3e56f40391565a855f.webpimage.png

          產(chǎn)生異常,存儲(chǔ)失敗。至于更多異常詳情嗎,參見 localstorage_功能檢測(cè)[4]:

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

          答案: 占空間

          鍵的數(shù)量,對(duì)讀寫的影響

          我們500 * 1000鍵,如下

          let?keyCount?=?500?*?1000;

          localStorage.clear();
          for?(let?i?=?0;?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

          你單獨(dú)執(zhí)行保存代碼:

          localStorage.clear();????
          console.time("save_cost");
          localStorage.setItem("a",?"1");
          console.timeEnd("save_cost");
          //?save_cost:?0.033203125?ms

          可以多次測(cè)試, 影響肯定是有的,也僅僅是數(shù)倍,不是特別的大。

          反過(guò)來(lái),如果是保存的值表較大呢?

          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

          可以多測(cè)試很多次,單次值的大小對(duì)存的性能影響非常大,讀取也一樣,合情合理之中。

          所以盡量不要保存大的值,因?yàn)槠涫峭阶x取,純大數(shù)據(jù),用indexedDB就好。

          答案:鍵的數(shù)量對(duì)讀取性能有影響,但是不大。值的大小對(duì)性能影響更大,不建議保存大的數(shù)據(jù)。

          寫個(gè)方法統(tǒng)計(jì)一個(gè)localStorage已使用空間

          現(xiàn)代瀏覽器的精寫版本:

          function?sieOfLS()?{
          ????return?Object.entries(localStorage).map(v?=>?v.join('')).join('').length;
          }

          測(cè)試代碼:

          localStorage.clear();
          localStorage.setItem("??",?1);
          localStorage.setItem("????????????????",?1111);
          console.log("size:",?sieOfLS())???//?23
          //???*9?+?1?*5?=?2*9?+?1*5?=?23

          html的協(xié)議標(biāo)準(zhǔn)

          WHATWG 超文本應(yīng)用程序技術(shù)工作組 的localstorage[5] 協(xié)議定了localStorage的方法,屬性等等,并沒有明確規(guī)定其存儲(chǔ)空間。也就導(dǎo)致各個(gè)瀏覽器的最大限制不一樣。

          其并不是ES的標(biāo)準(zhǔn)。

          頁(yè)面的utf-8編碼

          我們的html頁(yè)面,經(jīng)常會(huì)出現(xiàn)。告知瀏覽器此頁(yè)面屬于什么字符編碼格式,下一步瀏覽器做好解碼工作。


          ????
          ????
          ????
          ????容器

          這和localStorage的存儲(chǔ)沒有半毛錢的關(guān)系。

          localStorage擴(kuò)容

          localStorage的空間是 10M的字節(jié)數(shù),一般情況是夠用,可是人總是有貪欲。真達(dá)到了空間限制,怎么弄?

          localStorage擴(kuò)容就是一個(gè)話題。

          引用

          localStorage[6]

          參考資料

          [1]

          localStorage#description: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage#description

          [2]

          DOMString: https://developer.mozilla.org/en-US/docs/Web/API/DOMString

          [3]

          DOMString: https://developer.mozilla.org/en-US/docs/Web/API/DOMString

          [4]

          localstorage_功能檢測(cè): https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#localstorage_%E5%8A%9F%E8%83%BD%E6%A3%80%E6%B5%8B

          [5]

          localstorage: https://html.spec.whatwg.org/multipage/webstorage.html#dom-localstorage-dev

          [6]

          localStorage: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage


          瀏覽 104
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大粗鸡巴久久 | 亚洲免费观看高清视频 | 91久久精品日日躁夜夜躁欧美又粗又大 | 清纯粉嫩极品夜夜嗨AV | 青草无码视频在线观看 |