JavaScript 计算字符串在 localStorage 中的字节占用

作者:木棉

时间:2026-10-29

浏览:215

本文探讨如何在 JavaScript 中准确计算存入 localStorage 的字符串所占字节数。由于浏览器内部通常使用 UTF-16 编码存储字符串,直接按页面 UTF-8 编码计算可能导致容量判断失误。文章详细解析了 UTF-8 和 UTF-16 的编码规则,并通过代码示例展示了如何根据字符码点区分单字节、双字节、三字节及四字节的情况,确保写入操作符合存储限制。

文章目录

JavaScript 计算 localStorage 字符串字节数

近期开发中遇到一个实际需求,需要利用 JavaScript 计算一段字符串写入 localStorage 时所占用的内存大小。众所周知,JavaScript 内部采用 Unicode 编码处理字符串。Unicode 有多种实现方式,其中最常见的是 UTF-8 和 UTF-16。因此,本文仅针对这两种编码格式进行探讨。

以下定义引用自维基百科关于 UTF-8 的条目(http://zh.wikipedia.org/zh-cn/UTF-8),并进行了部分删减。

UTF-8(8-bit Unicode Transformation Format)是一种针对 Unicode 的可变长度字符编码,能够表示 Unicode 标准中的任何字符。其编码中的第一个字节与 ASCII 兼容,每个字符使用一至四个字节进行编码。

UTF-8 与 UTF-16 编码规则

其具体的编码规则如下:

若字符代码位于 000000 – 00007F 之间,则使用一个字节进行编码;

若字符代码位于 000080 – 0007FF 之间,则使用两个字节编码; 若字符代码位于 000800 – 00D7FF 和 00E000 – 00FFFF 之间,则使用三个字节编码。需要注意的是,Unicode 在 D800-DFFF 范围内不存在任何字符; 若字符代码位于 010000 – 10FFFF 之间,则使用四个字节编码。

而 UTF-16 则是定长的字符编码方式,大部分字符使用两个字节进行编码,字符代码超出 65535 的则使用四个字节,具体规则如下:

000000 – 00FFFF 使用两个字节; 010000 – 10FFFF 使用四个字节。

浏览器编码机制与测试验证

起初认为,既然页面采用 UTF-8 编码,那么存入 localStorage 的字符串也应遵循 UTF-8 编码。但测试结果显示,虽然计算出的大小不足 5MB,写入 localStorage 时却抛出了异常。考虑到页面编码是可以更改的,如果 localStorage 严格按照页面编码存储字符串,会导致情况混乱。实际上,浏览器内部通常使用 UTF-16 编码。使用 UTF-16 编码计算出的 5MB 字符串可以顺利写入,超出限制则会失败。

代码实现

以下是具体的代码实现。计算逻辑基于上述规则,为了提高执行速度,将两个 for 循环分开编写。


/**
   * 计算字符串所占的内存字节数,默认使用UTF-8的编码方式计算,也可制定为UTF-16
   * UTF-8 是一种可变长度的 Unicode 编码格式,使用一至四个字节为每个字符编码
   *
   * 000000 - 00007F(128个代码)   0zzzzzzz(00-7F)               一个字节
   * 000080 - 0007FF(1920个代码)   110yyyyy(C0-DF) 10zzzzzz(80-BF)       两个字节
   * 000800 - 00D7FF
    00E000 - 00FFFF(61440个代码)  1110xxxx(E0-EF) 10yyyyyy 10zzzzzz      三个字节
   * 010000 - 10FFFF(1048576个代码) 11110www(F0-F7) 10xxxxxx 10yyyyyy 10zzzzzz 四个字节
   *
   * 注: Unicode在范围 D800-DFFF 中不存在任何字符
   * {@link http://zh.wikipedia.org/wiki/UTF-8}
   *
   * UTF-16 大部分使用两个字节编码,编码超出 65535 的使用四个字节
   * 000000 - 00FFFF 两个字节
   * 010000 - 10FFFF 四个字节
   *
   * {@link http://zh.wikipedia.org/wiki/UTF-16}
   * @param {String} str
   * @param {String} charset utf-8, utf-16
   * @return {Number}
   */
  var sizeof = function(str, charset){
    var total = 0,
      charCode,
      i,
      len;
    charset = charset ? charset.toLowerCase() : '';
    if(charset === 'utf-16' || charset === 'utf16'){
      for(i = 0, len = str.length; i < len; i++){
        charCode = str.charCodeAt(i);
        if(charCode <= 0xffff){
          total += 2;
        }else{
          total += 4;
        }
      }
    }else{
      for(i = 0, len = str.length; i < len; i++){
        charCode = str.charCodeAt(i);
        if(charCode <= 0x007f) {
          total += 1;
        }else if(charCode <= 0x07ff){
          total += 2;
        }else if(charCode <= 0xffff){
          total += 3;
        }else{
          total += 4;
        }
      }
    }
    return total;
  }

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章