Open imeay opened 4 years ago
帮女朋友想一个匹配数字的输入的表达式, 要求整数或者小数,小数点后有且只能2位。 一会功夫,正则就出来了
/^(0|[1-9]\d*)(\.\d{1,2})?$/
验证过程中, 发现有一个奇怪的现象,数字 00 竟然也可以通过
> reg.test(00) true > reg.test('00') false
这个就让我很好奇了,为什么 数字 00 在这里竟然能通过正则表达式。 不禁想看下 RegExp.prototype.test 实现,在网上找下一下源码 https://chromium.googlesource.com/v8/v8/+/4.3.49/src/regexp.js?autodive=0%2F%2F 关键代码有2段 第一段是方法名映射
InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, GlobalArray( -- | "exec", RegExpExecJS, | "test", RegExpTest, | "toString", RegExpToString, | "compile", RegExpCompileJS | ));
第二段则是疑问的关键啦
function RegExpTest(string) { -- | if (!IS_REGEXP(this)) { | throw MakeTypeError('incompatible_method_receiver', | ['RegExp.prototype.test', this]); | } | string = TO_STRING_INLINE(string); | | var lastIndex = this.lastIndex; | | // Conversion is required by the ES5 specification (RegExp.prototype.exec | // algorithm, step 5) even if the value is discarded for non-global RegExps. | var i = TO_INTEGER(lastIndex); | | if (this.global \|\| (harmony_regexps && this.sticky)) { | if (i < 0 \|\| i > string.length) { | this.lastIndex = 0; | return false; | } | // matchIndices is either null or the $regexpLastMatchInfo array. | var matchIndices = %_RegExpExec(this, string, i, $regexpLastMatchInfo); | if (IS_NULL(matchIndices)) { | this.lastIndex = 0; | return false; | } | $regexpLastMatchInfoOverride = null; | this.lastIndex = $regexpLastMatchInfo[CAPTURE1]; | return true; | } else { | // Non-global, non-sticky regexp. | // Remove irrelevant preceeding '.*' in a test regexp. The expression | // checks whether this.source starts with '.*' and that the third char is | // not a '?'. But see https://code.google.com/p/v8/issues/detail?id=3560 | var regexp = this; | if (regexp.source.length >= 3 && | %_StringCharCodeAt(regexp.source, 0) == 46 && // '.' | %_StringCharCodeAt(regexp.source, 1) == 42 && // '*' | %_StringCharCodeAt(regexp.source, 2) != 63) { // '?' | regexp = TrimRegExp(regexp); | } | // matchIndices is either null or the $regexpLastMatchInfo array. | var matchIndices = %_RegExpExec(regexp, string, 0, $regexpLastMatchInfo); | if (IS_NULL(matchIndices)) { | this.lastIndex = 0; | return false; | } | $regexpLastMatchInfoOverride = null; | return true; | } | }
其中有一行代码 string = TO_STRING_INLINE(string); 引起了我的注意,这里将输入的参数在内部转成字符串, 在浏览器试了一下00转字符串
string = TO_STRING_INLINE(string);
String(00) "0"
结果输出为"0", 这也就是解释了上面验证通过的原因了 00 -> '"0" , 而字符串 0 刚好满足正则规则
Preview
帮女朋友想一个匹配数字的输入的表达式, 要求整数或者小数,小数点后有且只能2位。 一会功夫,正则就出来了
验证过程中, 发现有一个奇怪的现象,数字 00 竟然也可以通过
这个就让我很好奇了,为什么 数字 00 在这里竟然能通过正则表达式。 不禁想看下 RegExp.prototype.test 实现,在网上找下一下源码 https://chromium.googlesource.com/v8/v8/+/4.3.49/src/regexp.js?autodive=0%2F%2F 关键代码有2段 第一段是方法名映射
第二段则是疑问的关键啦
其中有一行代码
string = TO_STRING_INLINE(string);
引起了我的注意,这里将输入的参数在内部转成字符串, 在浏览器试了一下00转字符串结果输出为"0", 这也就是解释了上面验证通过的原因了 00 -> '"0" , 而字符串 0 刚好满足正则规则