Inputmask插件动态设置正则表达式时出现Uncaught RangeError: Maximum call stack size exceeded错误求助
我帮你排查了这个问题,你遇到的Uncaught RangeError: Maximum call stack size exceeded错误,根源在于id11对应的正则表达式里的非贪婪量词?与可选分组的组合,在你使用的Inputmask 4.0.9版本的正则解析逻辑中触发了无限递归的匹配循环,直接撑爆了调用栈。
你的id11正则是:^([0-9]{4}-[A-Z0-9]{13}?(-[0-9])?)$,这里的[A-Z0-9]{13}?是非贪婪匹配13个字符,再加上后面的可选分组(-[0-9])?,Inputmask在尝试解析这种带有可选分支的非贪婪模式时,会反复进行回溯匹配,最终陷入无限循环。
下面给你几个可行的解决方案:
方案1:调整正则表达式(最简单有效)
如果业务上不需要非贪婪匹配(这里的{13}?其实没有必要,因为后面的(-[0-9])?本身就是可选的,非贪婪模式在这里起不到实际作用),可以直接去掉非贪婪量词?,修改后的正则如下:
regex: '^([0-9]{4}-[A-Z0-9]{13}(-[0-9])?)$'
修改后,Inputmask可以正常解析该规则,不会再触发栈溢出,同时完全满足原有的匹配需求。
方案2:改用Inputmask原生掩码语法(更稳定)
Inputmask对复杂正则的支持在旧版本中存在兼容性问题,你可以用它的原生掩码语法替代纯正则,这种方式更稳定,也更符合插件的设计思路:
// 替换原有的正则设置代码 Inputmask({ mask: "9999-AAAAAAAAAAAAA[-9]", // 9匹配数字,A匹配字母数字 definitions: { 'A': { validator: "[A-Z0-9]" } }, greedy: false }).mask($('#idnumber'))
这种写法直接定义掩码格式,避免了正则解析的潜在bug。
方案3:升级Inputmask版本
你当前使用的4.0.9版本是2018年的旧版本,后续的5.x系列已经修复了大量正则解析的bug。升级到最新稳定版本后,可能不需要修改正则就能直接解决这个问题。
另外,建议你在代码里加个小判断,避免未选择ID类型或匹配不到规则时出现报错:
$(document).on('change', '#idtype', function() { let idNum = $('#idtype').val(); if (!idNum) return; // 未选择时直接返回 let getRegex = idTypes.filter(el => el.id == idNum); if (getRegex.length === 0) return; // 无匹配规则时返回 let regex = getRegex[0].regex; Inputmask.remove($('#idnumber')); Inputmask({ regex, greedy: false }).mask($('#idnumber')); })
完整修改后的代码示例(方案1)
$(document).ready(function() { let idTypes = [{ id: 1, name: 'id1', regex: '^([A-Za-z]{1}[0-9]{2}(-)[0-9]{2}(-)[0-9]{6})$' }, { id: 2, name: 'id2', regex: '(CRN-)[0-9]{4}-[0-9]{7}-[0-9]' }, { id: 3, name: 'id3', regex: '^(([0-9]{7}))$' }, { id: 4, name: 'id4', regex: '(PRN )([A-Za-z]{1}[0-9]{11}|([0-9]{12}))( [A-Za-z])' }, { id: 5, name: 'id5', regex: '^([A-Za-z]){1}([0-9]{7})([A-Za-z])$' }, { id: 7, name: 'id7', regex: '^([A-Za-z]){2}([0-9]{7})$' }, { id: 8, name: 'id8', regex: '([A-Z]{1}[0-9]{3}[A-Z]{4}[0-9]{2}[-][A-Z]{2}[0-9]{6})$' }, { id: 9, name: 'id9', regex: '([0-9]{5})$' }, { id: 10, name: 'id10', regex: '([0-9]{2}[-][0-9]{7}[-][0-9]{1})$' }, { id: 11, name: 'id11', // 去掉非贪婪量词? regex: '^([0-9]{4}-[A-Z0-9]{13}(-[0-9])?)$' }, ] $(document).on('change', '#idtype', function() { let idNum = $('#idtype').val(); if (!idNum) return; let getRegex = idTypes.filter(el => el.id == idNum); if (getRegex.length === 0) return; let regex = getRegex[0].regex; Inputmask.remove($('#idnumber')); Inputmask({ regex, greedy: false }).mask($('#idnumber')); }) })
内容的提问来源于stack exchange,提问作者eyeswrong36

