You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何JavaScript开发者不用string.length而用复杂函数计算字符串长度?

为什么这个函数要手动计算字符串的"字节长度"而不用str.length?

简单说:str.length返回的是字符串中Unicode代码单元的数量,而这个函数计算的是字符串在UTF-8编码下的字节总长度——这俩完全不是一回事儿!

先搞懂核心区别

在JavaScript里,字符串是用UTF-16编码存储的,每个"代码单元"占2字节,但不同Unicode字符在UTF-8编码下的字节占比不一样:

  • 对于ASCII字符(U+0000到U+007F):UTF-8编码占1字节,和str.length的计数一致
  • 对于U+0080到U+07FF的字符(比如部分欧洲语言特殊字符):UTF-8编码占2字节,str.length算1个单元,所以要额外加1
  • 对于U+0800到U+FFFF的字符(比如中文、日文):UTF-8编码占3字节,str.length算1个单元,所以要额外加2
  • 对于U+10000到U+10FFFF的字符(比如大部分emoji):JS里用代理对(两个UTF-16代码单元)表示,str.length算2,但UTF-8编码占4字节,这时候要特殊处理避免重复计数

拆解这个函数的逻辑

function byteLength(str) { 
  // returns the byte length of an utf8 string 
  var s = str.length; 
  for (var i=str.length-1; i>=0; i--) { 
    var code = str.charCodeAt(i); 
    if (code > 0x7f && code <= 0x7ff) s++; 
    else if (code > 0x7ff && code <= 0xffff) s+=2; 
    if (code >= 0xDC00 && code <= 0xDFFF) i--; //trail surrogate 
  } 
  return s; 
}

咱们一步步看:

  1. 初始值s = str.length:先拿JS内部的代码单元数量当基础计数
  2. 从后往前遍历每个字符的编码:
    • 如果字符是U+0080到U+07FF之间的:UTF-8比代码单元多占1字节,所以s++
    • 如果字符是U+0800到U+FFFF之间的:UTF-8比代码单元多占2字节,所以s+=2
    • 如果遇到低代理字符(0xDC00到0xDFFF):这是代理对的后半部分,对应的前半部分(高代理)已经被处理过了,所以i--跳过它,避免重复计算代理对的字节数

举个实际例子对比

  • 普通ASCII字符"a":str.length=1,函数返回1(UTF-8占1字节,正确)
  • 中文"中":str.length=1,函数返回3(UTF-8编码确实是3字节,正确)
  • Emoji"😀":str.length=2(代理对),函数返回4(UTF-8编码占4字节,正确)

如果直接用str.length,上面后两个例子的结果就完全不对了——这就是为什么开发者要写这个函数:他们需要的是字符串转成UTF-8后的实际字节数,而不是JS内部存储的代码单元数量。

内容的提问来源于stack exchange,提问作者Diagathe Josué

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:51:33