charCodeAt本身不加密,仅返回字符UTF-16码点值(0–65535),明文一一对应、无密钥、不可逆、无混淆;处理非BMP字符需改用codePointAt,且此类变换无密码学安全性。

charCodeAt 本身不加密,只是获取编码值
charCodeAt 返回的是字符在 UTF-16 编码表中的数值(0–65535),它不加密,也不混淆。你拿到的 65 就是 'A' 的码点,和明文一一对应。直接用它“当加密”等于把文本转成一串数字——没有密钥、不可逆、无混淆,任何懂 JS 的人一眼就能还原。
如果真想实现基础文本变换,得把它作为中间步骤,配合位运算、偏移或简单替换逻辑来用。比如加一个固定偏移量再转回字符,才勉强算“可逆变换”:
function simpleEncode(str, offset = 3) {
return str.split('').map(c => String.fromCharCode(c.charCodeAt(0) + offset)).join('');
}
别用 charCodeAt 处理非 BMP 字符
中文、emoji(如 ?)、古汉字等很多字符属于 Unicode 辅助平面(U+10000 及以上),在 JS 中以两个 16 位代理对(surrogate pair)存储。charCodeAt 每次只读一个 16 位单元,遇到这类字符会返回错误的中间值(比如 '?'.charCodeAt(0) 是 55357,不是真实码点)。
正确做法是改用 codePointAt:
-
str.charCodeAt(i)→ 只适用于基本多语言平面(BMP)字符(U+0000–U+FFFF) -
str.codePointAt(i)→ 支持全部 Unicode 字符,返回完整码点(如'?'.codePointAt(0)是127757) - 遍历时需跳过代理对第二部分:若
codePointAt(i)返回值 > 0xFFFF,则下标要i += 2
加密强度极低,仅限教学或临时混淆
哪怕加上偏移、异或或简单轮转,这种基于 charCodeAt 的变换也完全不具备密码学安全性:
- 没有密钥派生,偏移量硬编码即等于密钥明文暴露
- 无扩散性:一个字符变,只影响自己,无法隐藏统计特征
- 无法抵抗已知明文攻击——只要知道几组“原文→数字序列”,立刻能反推规则
- 现代浏览器中,源码可见,
eval或调试器几秒就能还原逻辑
真有保密需求,必须用标准算法(如 Web Crypto API 的 SubtleCrypto.encrypt)配合安全随机密钥。
常见误用:把数字数组当密文直接传输
有人把 'hello'.split('').map(c => c.charCodeAt(0)) 得到的 [104, 101, 108, 108, 111] 当作“加密结果”发给后端,这是危险的:
- 前端 JSON 序列化后仍是纯数字数组,无任何混淆
- 服务端若不做校验直接
String.fromCharCode(...arr)还原,就等于裸传明文 - 若中间被截获,攻击者连解码都不用,直接查 ASCII 表就能读出原文
如果只是想防随手查看,至少做一层 Base64 或十六进制编码;但请记住:这仍不是加密,只是编码。
真正难的不是怎么用 charCodeAt,而是意识到它离“加密”有多远——它连门槛都还没跨过去。

















