document.getelementbyid("pwd").length 失效,是因为 dom 元素对象本身无 .length 属性;必须先通过 .value 获取字符串值,再取 .length,即 document.getelementbyid("pwd").value.length。

为什么直接写 input.length 会失效
很多人一上来就写 document.getElementById("pwd").length,结果发现永远是 undefined 或 0。这不是浏览器 bug,而是对象搞错了:DOM 元素本身没有 .length 表示内容长度,它只有 .value 属性存字符串,而字符串才有 .length。
必须先取值再算长度:
const pwdInput = document.getElementById("pwd");
const pwdLength = pwdInput.value.length; // ✅ 正确
- 如果用 React/Vue 等框架,还要注意受控组件中
value来自 state,不能只靠原生 DOM 读取 -
input.value在用户还没输入时是空字符串,.length就是 0,别漏判 - 移动端软键盘弹出后焦点丢失,可能让
value读取时机错乱,建议绑定input事件而非blur做实时校验
maxlength 和 minlength 在 password 类型上是否生效
生效,但仅限于“阻止新增输入”,不是“保证数据合规”。type="password" 明确在支持列表里,所以写 maxlength="16" 后,用户敲第 17 个字符会被静默拦截(连 input 事件都不触发)。
但以下情况它完全不管:
- 用户粘贴超长密码 → 大部分浏览器照单全收,然后才发
input事件 - JS 动态赋值:
pwdInput.value = "a".repeat(20)→ 值照设,不截断 - 表单提交时默认不校验
maxlength,哪怕值超了也能成功提交
想让它参与提交校验,得手动绑定:
pwdInput.addEventListener("input", () => {
const tooLong = pwdInput.value.length > 16;
pwdInput.setCustomValidity(tooLong ? "密码不能超过16位" : "");
});
如何真正拦住粘贴和 JS 赋值导致的超长输入
原生 maxlength 对粘贴和脚本写入无能为力,必须用 JS 主动截断。但直接 el.value = el.value.slice(0, 16) 有副作用:光标会跳到末尾,用户继续打字会从最后开始,体验极差。
更稳妥的做法是保留光标位置:
- 监听
input和paste两个事件 - 在
paste的beforeinput阶段(若支持)或paste的setTimeout延迟中截断 - 用
el.setRangeText()替代直接赋值,它能维持选区和光标
简化版兼容写法:
pwdInput.addEventListener("input", () => {
if (pwdInput.value.length > 16) {
const start = pwdInput.selectionStart;
pwdInput.value = pwdInput.value.slice(0, 16);
pwdInput.setSelectionRange(start, start); // 尽量还原光标
}
});
为什么后端校验不可省略,哪怕前端做了双保险
所有前端限制都可绕过:禁用 JS、删掉 maxlength、curl 直接 POST、甚至用 Burp Suite 改请求体。更关键的是计数逻辑差异:
- 前端
.length按 UTF-16 码元算 → 一个 ?? 占 2 位,前端maxlength="10"实际只能输 5 个国旗 emoji - 后端按 UTF-8 字节校验 → 同一个 ?? 是 4 字节,10 字节限制下可能只容得下 2 个
- 用户复制带不可见控制符(如
\u200b)的密码,前端没过滤,后端入库可能失败或被用于注入
所以最终提交前,后端必须独立做长度+编码+内容清洗,前端只是挡掉大部分误操作。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











