[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fexec":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fexec":1908,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fexec":1934},{"source":4,"connector":5,"page":6},"sqlite","better-sqlite3",{"path":7,"title":8,"description":9,"category":10,"tags":11,"date":14,"pinned":15,"draft":15,"body":16,"seo":1904,"stem":1905,"id":1906,"extension":1907},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fexec","正则表达式","JavaScript 使用 ECMAScript RegExp 实现，支持贪婪\u002F惰性量词、断言与 matchAll 等。","技能小册",[12,13],"javascript","exec","2022-05-21",false,{"type":17,"value":18,"toc":1868},"minimark",[19,22,39,44,49,66,181,185,191,251,270,274,285,289,376,380,478,485,592,596,599,674,678,754,758,815,823,911,919,1012,1043,1053,1060,1070,1279,1286,1296,1452,1464,1468,1479,1483,1528,1533,1566,1570,1582,1586,1700,1716,1719,1795,1798,1801,1804,1864],[20,21,8],"h1",{"id":8},[23,24,25,26,33,34,38],"p",{},"JavaScript 使用 ",[27,28,32],"a",{"href":29,"rel":30},"https:\u002F\u002Ftc39.es\u002Fecma262\u002F#sec-regexp-regular-expression-objects",[31],"nofollow","ECMAScript RegExp"," 实现，支持贪婪\u002F惰性量词、断言与 ",[35,36,37],"code",{},"matchAll"," 等。",[40,41,43],"h2",{"id":42},"一贪婪与惰性匹配","一、贪婪与惰性匹配",[45,46,48],"h3",{"id":47},"_1-贪婪匹配默认","1. 贪婪匹配（默认）",[23,50,51,52,55,56,55,59,55,62,65],{},"量词（",[35,53,54],{},"*","、",[35,57,58],{},"+",[35,60,61],{},"?",[35,63,64],{},"{m,n}"," 等）在默认情况下会匹配尽可能多的字符。",[67,68,73],"pre",{"className":69,"code":70,"language":71,"meta":72,"style":72},"language-js shiki shiki-themes material-theme-lighter github-light github-dark","const str = \"\u003Cdiv>content\u003C\u002Fdiv>\u003Cspan>text\u003C\u002Fspan>\";\nconst greedy = \u002F\u003C.*>\u002F; \u002F\u002F 匹配从第一个 \u003C 到最后一个 >\nconsole.log(greedy.exec(str)[0]);\n\u002F\u002F 输出: \"\u003Cdiv>content\u003C\u002Fdiv>\u003Cspan>text\u003C\u002Fspan>\" （整个字符串）\n","js","",[35,74,75,107,143,175],{"__ignoreMap":72},[76,77,80,84,88,92,96,100,103],"span",{"class":78,"line":79},"line",1,[76,81,83],{"class":82},"sbsja","const",[76,85,87],{"class":86},"s_hVV"," str",[76,89,91],{"class":90},"smGrS"," =",[76,93,95],{"class":94},"sjJ54"," \"",[76,97,99],{"class":98},"s_sjI","\u003Cdiv>content\u003C\u002Fdiv>\u003Cspan>text\u003C\u002Fspan>",[76,101,102],{"class":94},"\"",[76,104,106],{"class":105},"sP7_E",";\n",[76,108,110,112,115,117,120,124,128,130,133,136,139],{"class":78,"line":109},2,[76,111,83],{"class":82},[76,113,114],{"class":86}," greedy",[76,116,91],{"class":90},[76,118,119],{"class":94}," \u002F",[76,121,123],{"class":122},"sQRbd","\u003C",[76,125,127],{"class":126},"stzsN",".",[76,129,54],{"class":90},[76,131,132],{"class":122},">",[76,134,135],{"class":94},"\u002F",[76,137,138],{"class":105},";",[76,140,142],{"class":141},"sutJx"," \u002F\u002F 匹配从第一个 \u003C 到最后一个 >\n",[76,144,146,150,152,156,159,161,163,166,170,173],{"class":78,"line":145},3,[76,147,149],{"class":148},"su5hD","console",[76,151,127],{"class":105},[76,153,155],{"class":154},"sGLFI","log",[76,157,158],{"class":148},"(greedy",[76,160,127],{"class":105},[76,162,13],{"class":154},[76,164,165],{"class":148},"(str)[",[76,167,169],{"class":168},"srdBf","0",[76,171,172],{"class":148},"])",[76,174,106],{"class":105},[76,176,178],{"class":78,"line":177},4,[76,179,180],{"class":141},"\u002F\u002F 输出: \"\u003Cdiv>content\u003C\u002Fdiv>\u003Cspan>text\u003C\u002Fspan>\" （整个字符串）\n",[45,182,184],{"id":183},"_2-惰性匹配非贪婪","2. 惰性匹配（非贪婪）",[23,186,187,188,190],{},"在量词后添加 ",[35,189,61],{}," 使其匹配尽可能少的字符。常用语提取 HTML 标签内的内容。",[67,192,194],{"className":69,"code":193,"language":71,"meta":72,"style":72},"const lazy = \u002F\u003C.*?>\u002F; \u002F\u002F 匹配最短的 \u003C...>\nconsole.log(lazy.exec(str)[0]);\n\u002F\u002F 输出: \"\u003Cdiv>\" （只匹配第一个标签）\n",[35,195,196,223,246],{"__ignoreMap":72},[76,197,198,200,203,205,207,209,211,214,216,218,220],{"class":78,"line":79},[76,199,83],{"class":82},[76,201,202],{"class":86}," lazy",[76,204,91],{"class":90},[76,206,119],{"class":94},[76,208,123],{"class":122},[76,210,127],{"class":126},[76,212,213],{"class":90},"*?",[76,215,132],{"class":122},[76,217,135],{"class":94},[76,219,138],{"class":105},[76,221,222],{"class":141}," \u002F\u002F 匹配最短的 \u003C...>\n",[76,224,225,227,229,231,234,236,238,240,242,244],{"class":78,"line":109},[76,226,149],{"class":148},[76,228,127],{"class":105},[76,230,155],{"class":154},[76,232,233],{"class":148},"(lazy",[76,235,127],{"class":105},[76,237,13],{"class":154},[76,239,165],{"class":148},[76,241,169],{"class":168},[76,243,172],{"class":148},[76,245,106],{"class":105},[76,247,248],{"class":78,"line":145},[76,249,250],{"class":141},"\u002F\u002F 输出: \"\u003Cdiv>\" （只匹配第一个标签）\n",[23,252,253,257,258,55,260,55,263,55,266,269],{},[254,255,256],"strong",{},"常用惰性量词","：",[35,259,213],{},[35,261,262],{},"+?",[35,264,265],{},"??",[35,267,268],{},"{m,n}?","。",[40,271,273],{"id":272},"二反向引用backreference","二、反向引用（Backreference）",[23,275,276,277,280,281,284],{},"反向引用允许你在正则表达式中引用前面捕获组匹配的内容。语法为 ",[35,278,279],{},"\\1",", ",[35,282,283],{},"\\2"," ...（数字对应捕获组顺序）。",[45,286,288],{"id":287},"_1-匹配重复单词","1. 匹配重复单词",[67,290,292],{"className":69,"code":291,"language":71,"meta":72,"style":72},"const str = \"hello hello world\";\nconst regex = \u002F\\b(\\w+)\\s+\\1\\b\u002F;\nconsole.log(regex.test(str)); \u002F\u002F true\n",[35,293,294,311,352],{"__ignoreMap":72},[76,295,296,298,300,302,304,307,309],{"class":78,"line":79},[76,297,83],{"class":82},[76,299,87],{"class":86},[76,301,91],{"class":90},[76,303,95],{"class":94},[76,305,306],{"class":98},"hello hello world",[76,308,102],{"class":94},[76,310,106],{"class":105},[76,312,313,315,318,320,322,326,330,333,335,338,341,343,346,348,350],{"class":78,"line":109},[76,314,83],{"class":82},[76,316,317],{"class":86}," regex",[76,319,91],{"class":90},[76,321,119],{"class":94},[76,323,325],{"class":324},"sVHd0","\\b",[76,327,329],{"class":328},"s-KJb","(",[76,331,332],{"class":126},"\\w",[76,334,58],{"class":90},[76,336,337],{"class":328},")",[76,339,340],{"class":126},"\\s",[76,342,58],{"class":90},[76,344,279],{"class":345},"sw1J6",[76,347,325],{"class":324},[76,349,135],{"class":94},[76,351,106],{"class":105},[76,353,354,356,358,360,363,365,368,371,373],{"class":78,"line":145},[76,355,149],{"class":148},[76,357,127],{"class":105},[76,359,155],{"class":154},[76,361,362],{"class":148},"(regex",[76,364,127],{"class":105},[76,366,367],{"class":154},"test",[76,369,370],{"class":148},"(str))",[76,372,138],{"class":105},[76,374,375],{"class":141}," \u002F\u002F true\n",[45,377,379],{"id":378},"_2-匹配成对标签","2. 匹配成对标签",[67,381,383],{"className":69,"code":382,"language":71,"meta":72,"style":72},"const html = \"\u003Cdiv>content\u003C\u002Fdiv>\u003Cspan>text\u003C\u002Fp>\";\nconst tagRegex = \u002F\u003C([a-z]+)>.*?\u003C\\\u002F\\1>\u002Fi;\nconsole.log(tagRegex.test(html)); \u002F\u002F false，因为第二个标签不匹配\n",[35,384,385,403,455],{"__ignoreMap":72},[76,386,387,389,392,394,396,399,401],{"class":78,"line":79},[76,388,83],{"class":82},[76,390,391],{"class":86}," html",[76,393,91],{"class":90},[76,395,95],{"class":94},[76,397,398],{"class":98},"\u003Cdiv>content\u003C\u002Fdiv>\u003Cspan>text\u003C\u002Fp>",[76,400,102],{"class":94},[76,402,106],{"class":105},[76,404,405,407,410,412,414,416,418,422,425,428,430,432,434,436,438,440,444,446,448,450,453],{"class":78,"line":109},[76,406,83],{"class":82},[76,408,409],{"class":86}," tagRegex",[76,411,91],{"class":90},[76,413,119],{"class":94},[76,415,123],{"class":122},[76,417,329],{"class":328},[76,419,421],{"class":420},"s39Yj","[",[76,423,424],{"class":126},"a-z",[76,426,427],{"class":420},"]",[76,429,58],{"class":90},[76,431,337],{"class":328},[76,433,132],{"class":122},[76,435,127],{"class":126},[76,437,213],{"class":90},[76,439,123],{"class":122},[76,441,443],{"class":442},"sjYin","\\\u002F",[76,445,279],{"class":345},[76,447,132],{"class":122},[76,449,135],{"class":94},[76,451,452],{"class":345},"i",[76,454,106],{"class":105},[76,456,457,459,461,463,466,468,470,473,475],{"class":78,"line":145},[76,458,149],{"class":148},[76,460,127],{"class":105},[76,462,155],{"class":154},[76,464,465],{"class":148},"(tagRegex",[76,467,127],{"class":105},[76,469,367],{"class":154},[76,471,472],{"class":148},"(html))",[76,474,138],{"class":105},[76,476,477],{"class":141}," \u002F\u002F false，因为第二个标签不匹配\n",[45,479,481,482],{"id":480},"_3-在替换中使用-1","3. 在替换中使用 ",[35,483,484],{},"$1",[67,486,488],{"className":69,"code":487,"language":71,"meta":72,"style":72},"const date = \"2025-04-25\";\nconst newDate = date.replace(\u002F(\\d{4})-(\\d{2})-(\\d{2})\u002F, \"$3\u002F$2\u002F$1\");\nconsole.log(newDate); \u002F\u002F \"25\u002F04\u002F2025\"\n",[35,489,490,508,576],{"__ignoreMap":72},[76,491,492,494,497,499,501,504,506],{"class":78,"line":79},[76,493,83],{"class":82},[76,495,496],{"class":86}," date",[76,498,91],{"class":90},[76,500,95],{"class":94},[76,502,503],{"class":98},"2025-04-25",[76,505,102],{"class":94},[76,507,106],{"class":105},[76,509,510,512,515,517,519,521,524,526,528,530,533,536,538,541,543,545,548,550,552,554,556,558,560,562,565,567,570,572,574],{"class":78,"line":109},[76,511,83],{"class":82},[76,513,514],{"class":86}," newDate",[76,516,91],{"class":90},[76,518,496],{"class":148},[76,520,127],{"class":105},[76,522,523],{"class":154},"replace",[76,525,329],{"class":148},[76,527,135],{"class":94},[76,529,329],{"class":328},[76,531,532],{"class":126},"\\d",[76,534,535],{"class":90},"{4}",[76,537,337],{"class":328},[76,539,540],{"class":122},"-",[76,542,329],{"class":328},[76,544,532],{"class":126},[76,546,547],{"class":90},"{2}",[76,549,337],{"class":328},[76,551,540],{"class":122},[76,553,329],{"class":328},[76,555,532],{"class":126},[76,557,547],{"class":90},[76,559,337],{"class":328},[76,561,135],{"class":94},[76,563,564],{"class":105},",",[76,566,95],{"class":94},[76,568,569],{"class":98},"$3\u002F$2\u002F$1",[76,571,102],{"class":94},[76,573,337],{"class":148},[76,575,106],{"class":105},[76,577,578,580,582,584,587,589],{"class":78,"line":145},[76,579,149],{"class":148},[76,581,127],{"class":105},[76,583,155],{"class":154},[76,585,586],{"class":148},"(newDate)",[76,588,138],{"class":105},[76,590,591],{"class":141}," \u002F\u002F \"25\u002F04\u002F2025\"\n",[40,593,595],{"id":594},"三前瞻与后顾lookahead-lookbehind","三、前瞻与后顾（Lookahead & Lookbehind）",[23,597,598],{},"断言匹配位置而不消耗字符，分为正向（肯定）和负向（否定）。",[600,601,602,618],"table",{},[603,604,605],"thead",{},[606,607,608,612,615],"tr",{},[609,610,611],"th",{},"类型",[609,613,614],{},"语法",[609,616,617],{},"含义",[619,620,621,635,648,661],"tbody",{},[606,622,623,627,632],{},[624,625,626],"td",{},"正向前瞻",[624,628,629],{},[35,630,631],{},"(?=...)",[624,633,634],{},"后面必须跟着 ...",[606,636,637,640,645],{},[624,638,639],{},"负向前瞻",[624,641,642],{},[35,643,644],{},"(?!...)",[624,646,647],{},"后面不能跟着 ...",[606,649,650,653,658],{},[624,651,652],{},"正向后顾",[624,654,655],{},[35,656,657],{},"(?\u003C=...)",[624,659,660],{},"前面必须是 ...（ES2018 支持）",[606,662,663,666,671],{},[624,664,665],{},"负向后顾",[624,667,668],{},[35,669,670],{},"(?\u003C!...)",[624,672,673],{},"前面不能是 ...（ES2018 支持）",[45,675,677],{"id":676},"_1-正向前瞻匹配后面是数字的字母","1. 正向前瞻：匹配后面是数字的字母",[67,679,681],{"className":69,"code":680,"language":71,"meta":72,"style":72},"const str = \"a1 b2 c3 d\";\nconst regex = \u002F[a-z](?=\\d)\u002Fg;\nconsole.log(str.match(regex)); \u002F\u002F ['a','b','c']\n",[35,682,683,700,730],{"__ignoreMap":72},[76,684,685,687,689,691,693,696,698],{"class":78,"line":79},[76,686,83],{"class":82},[76,688,87],{"class":86},[76,690,91],{"class":90},[76,692,95],{"class":94},[76,694,695],{"class":98},"a1 b2 c3 d",[76,697,102],{"class":94},[76,699,106],{"class":105},[76,701,702,704,706,708,710,712,714,716,719,721,723,725,728],{"class":78,"line":109},[76,703,83],{"class":82},[76,705,317],{"class":86},[76,707,91],{"class":90},[76,709,119],{"class":94},[76,711,421],{"class":420},[76,713,424],{"class":126},[76,715,427],{"class":420},[76,717,718],{"class":328},"(?=",[76,720,532],{"class":126},[76,722,337],{"class":328},[76,724,135],{"class":94},[76,726,727],{"class":345},"g",[76,729,106],{"class":105},[76,731,732,734,736,738,741,743,746,749,751],{"class":78,"line":145},[76,733,149],{"class":148},[76,735,127],{"class":105},[76,737,155],{"class":154},[76,739,740],{"class":148},"(str",[76,742,127],{"class":105},[76,744,745],{"class":154},"match",[76,747,748],{"class":148},"(regex))",[76,750,138],{"class":105},[76,752,753],{"class":141}," \u002F\u002F ['a','b','c']\n",[45,755,757],{"id":756},"_2-负向前瞻匹配后面不是数字的字母","2. 负向前瞻：匹配后面不是数字的字母",[67,759,761],{"className":69,"code":760,"language":71,"meta":72,"style":72},"const regex2 = \u002F[a-z](?!\\d)\u002Fg;\nconsole.log(str.match(regex2)); \u002F\u002F ['d']\n",[35,762,763,793],{"__ignoreMap":72},[76,764,765,767,770,772,774,776,778,780,783,785,787,789,791],{"class":78,"line":79},[76,766,83],{"class":82},[76,768,769],{"class":86}," regex2",[76,771,91],{"class":90},[76,773,119],{"class":94},[76,775,421],{"class":420},[76,777,424],{"class":126},[76,779,427],{"class":420},[76,781,782],{"class":328},"(?!",[76,784,532],{"class":126},[76,786,337],{"class":328},[76,788,135],{"class":94},[76,790,727],{"class":345},[76,792,106],{"class":105},[76,794,795,797,799,801,803,805,807,810,812],{"class":78,"line":109},[76,796,149],{"class":148},[76,798,127],{"class":105},[76,800,155],{"class":154},[76,802,740],{"class":148},[76,804,127],{"class":105},[76,806,745],{"class":154},[76,808,809],{"class":148},"(regex2))",[76,811,138],{"class":105},[76,813,814],{"class":141}," \u002F\u002F ['d']\n",[45,816,818,819,822],{"id":817},"_3-正向后顾匹配前面是-的用户名","3. 正向后顾：匹配前面是 ",[35,820,821],{},"@"," 的用户名",[67,824,826],{"className":69,"code":825,"language":71,"meta":72,"style":72},"const text = \"email: user@example.com, contact@test.org\";\nconst regex = \u002F(?\u003C=@)[a-z0-9.-]+\\.[a-z]+\u002Fg;\nconsole.log(text.match(regex)); \u002F\u002F ['example.com', 'test.org']\n",[35,827,828,846,889],{"__ignoreMap":72},[76,829,830,832,835,837,839,842,844],{"class":78,"line":79},[76,831,83],{"class":82},[76,833,834],{"class":86}," text",[76,836,91],{"class":90},[76,838,95],{"class":94},[76,840,841],{"class":98},"email: user@example.com, contact@test.org",[76,843,102],{"class":94},[76,845,106],{"class":105},[76,847,848,850,852,854,856,859,861,863,865,868,870,872,875,877,879,881,883,885,887],{"class":78,"line":109},[76,849,83],{"class":82},[76,851,317],{"class":86},[76,853,91],{"class":90},[76,855,119],{"class":94},[76,857,858],{"class":328},"(?\u003C=",[76,860,821],{"class":122},[76,862,337],{"class":328},[76,864,421],{"class":420},[76,866,867],{"class":126},"a-z0-9.-",[76,869,427],{"class":420},[76,871,58],{"class":90},[76,873,874],{"class":442},"\\.",[76,876,421],{"class":420},[76,878,424],{"class":126},[76,880,427],{"class":420},[76,882,58],{"class":90},[76,884,135],{"class":94},[76,886,727],{"class":345},[76,888,106],{"class":105},[76,890,891,893,895,897,900,902,904,906,908],{"class":78,"line":145},[76,892,149],{"class":148},[76,894,127],{"class":105},[76,896,155],{"class":154},[76,898,899],{"class":148},"(text",[76,901,127],{"class":105},[76,903,745],{"class":154},[76,905,748],{"class":148},[76,907,138],{"class":105},[76,909,910],{"class":141}," \u002F\u002F ['example.com', 'test.org']\n",[45,912,914,915,918],{"id":913},"_4-负向前瞻匹配协议不是-https-的-url","4. 负向前瞻：匹配协议不是 ",[35,916,917],{},"https"," 的 URL",[67,920,922],{"className":69,"code":921,"language":71,"meta":72,"style":72},"const urls = \"http:\u002F\u002Fexample.com https:\u002F\u002Fsecure.com ftp:\u002F\u002Ffiles.com\";\nconst regex = \u002F\\b(?!https:\\\u002F\\\u002F)\\w+:\\\u002F\\\u002F[^\\s]+\u002Fg;\nconsole.log(urls.match(regex)); \u002F\u002F ['http:\u002F\u002Fexample.com', 'ftp:\u002F\u002Ffiles.com']\n",[35,923,924,942,990],{"__ignoreMap":72},[76,925,926,928,931,933,935,938,940],{"class":78,"line":79},[76,927,83],{"class":82},[76,929,930],{"class":86}," urls",[76,932,91],{"class":90},[76,934,95],{"class":94},[76,936,937],{"class":98},"http:\u002F\u002Fexample.com https:\u002F\u002Fsecure.com ftp:\u002F\u002Ffiles.com",[76,939,102],{"class":94},[76,941,106],{"class":105},[76,943,944,946,948,950,952,954,956,959,962,964,966,968,971,973,975,978,980,982,984,986,988],{"class":78,"line":109},[76,945,83],{"class":82},[76,947,317],{"class":86},[76,949,91],{"class":90},[76,951,119],{"class":94},[76,953,325],{"class":324},[76,955,782],{"class":328},[76,957,958],{"class":122},"https:",[76,960,961],{"class":442},"\\\u002F\\\u002F",[76,963,337],{"class":328},[76,965,332],{"class":126},[76,967,58],{"class":90},[76,969,970],{"class":122},":",[76,972,961],{"class":442},[76,974,421],{"class":420},[76,976,977],{"class":90},"^",[76,979,340],{"class":126},[76,981,427],{"class":420},[76,983,58],{"class":90},[76,985,135],{"class":94},[76,987,727],{"class":345},[76,989,106],{"class":105},[76,991,992,994,996,998,1001,1003,1005,1007,1009],{"class":78,"line":145},[76,993,149],{"class":148},[76,995,127],{"class":105},[76,997,155],{"class":154},[76,999,1000],{"class":148},"(urls",[76,1002,127],{"class":105},[76,1004,745],{"class":154},[76,1006,748],{"class":148},[76,1008,138],{"class":105},[76,1010,1011],{"class":141}," \u002F\u002F ['http:\u002F\u002Fexample.com', 'ftp:\u002F\u002Ffiles.com']\n",[23,1013,1014,1017,1018,1021,1022,1024,1025,1028,1029,1032,1033,1035,1036,1039,1040,1042],{},[254,1015,1016],{},"注意","：此处用负向",[254,1019,1020],{},"前瞻","而非后顾——",[35,1023,325],{}," 定位在协议名开头，紧接着判断后面是否为 ",[35,1026,1027],{},"https:\u002F\u002F","。若改用后顾 ",[35,1030,1031],{},"(?\u003C!https:\\\u002F\\\u002F)\\b...","，断言检查的是 ",[35,1034,325],{}," ",[254,1037,1038],{},"前面","的内容，而字符串开头或空格处并不是 ",[35,1041,1027],{},"，因此该断言恒为真，不会起到排除作用，实际会匹配出全部三个 URL。",[40,1044,1046,1047,1049,1050,1052],{"id":1045},"四exec-与-matchall-的迭代使用","四、",[35,1048,13],{}," 与 ",[35,1051,37],{}," 的迭代使用",[45,1054,1056,1057],{"id":1055},"_1-regexpprototypeexec","1. ",[35,1058,1059],{},"RegExp.prototype.exec",[23,1061,1062,1063,1066,1067,269],{},"每次调用返回下一个匹配结果（带捕获组），直到 ",[35,1064,1065],{},"null","。需要手动维护 ",[35,1068,1069],{},"lastIndex",[67,1071,1073],{"className":69,"code":1072,"language":71,"meta":72,"style":72},"const regex = \u002F(\\d{4})-(\\d{2})-(\\d{2})\u002Fg;\nconst str = \"2025-04-25, 2026-01-01\";\nlet match;\nwhile ((match = regex.exec(str)) !== null) {\n    console.log(\n        `Full: ${match[0]}, Year: ${match[1]}, Month: ${match[2]}, Day: ${match[3]}`\n    );\n}\n",[35,1074,1075,1119,1136,1146,1178,1192,1265,1273],{"__ignoreMap":72},[76,1076,1077,1079,1081,1083,1085,1087,1089,1091,1093,1095,1097,1099,1101,1103,1105,1107,1109,1111,1113,1115,1117],{"class":78,"line":79},[76,1078,83],{"class":82},[76,1080,317],{"class":86},[76,1082,91],{"class":90},[76,1084,119],{"class":94},[76,1086,329],{"class":328},[76,1088,532],{"class":126},[76,1090,535],{"class":90},[76,1092,337],{"class":328},[76,1094,540],{"class":122},[76,1096,329],{"class":328},[76,1098,532],{"class":126},[76,1100,547],{"class":90},[76,1102,337],{"class":328},[76,1104,540],{"class":122},[76,1106,329],{"class":328},[76,1108,532],{"class":126},[76,1110,547],{"class":90},[76,1112,337],{"class":328},[76,1114,135],{"class":94},[76,1116,727],{"class":345},[76,1118,106],{"class":105},[76,1120,1121,1123,1125,1127,1129,1132,1134],{"class":78,"line":109},[76,1122,83],{"class":82},[76,1124,87],{"class":86},[76,1126,91],{"class":90},[76,1128,95],{"class":94},[76,1130,1131],{"class":98},"2025-04-25, 2026-01-01",[76,1133,102],{"class":94},[76,1135,106],{"class":105},[76,1137,1138,1141,1144],{"class":78,"line":145},[76,1139,1140],{"class":82},"let",[76,1142,1143],{"class":148}," match",[76,1145,106],{"class":105},[76,1147,1148,1151,1154,1157,1159,1161,1163,1166,1169,1172,1175],{"class":78,"line":177},[76,1149,1150],{"class":324},"while",[76,1152,1153],{"class":148}," ((match ",[76,1155,1156],{"class":90},"=",[76,1158,317],{"class":148},[76,1160,127],{"class":105},[76,1162,13],{"class":154},[76,1164,1165],{"class":148},"(str)) ",[76,1167,1168],{"class":90},"!==",[76,1170,1171],{"class":420}," null",[76,1173,1174],{"class":148},") ",[76,1176,1177],{"class":105},"{\n",[76,1179,1181,1184,1186,1188],{"class":78,"line":1180},5,[76,1182,1183],{"class":148},"    console",[76,1185,127],{"class":105},[76,1187,155],{"class":154},[76,1189,1191],{"class":1190},"skxfh","(\n",[76,1193,1195,1198,1201,1204,1206,1209,1211,1213,1216,1219,1221,1223,1225,1228,1230,1232,1235,1237,1239,1241,1244,1246,1248,1251,1253,1255,1257,1260,1262],{"class":78,"line":1194},6,[76,1196,1197],{"class":94},"        `",[76,1199,1200],{"class":98},"Full: ",[76,1202,1203],{"class":94},"${",[76,1205,745],{"class":148},[76,1207,421],{"class":1208},"sfo-9",[76,1210,169],{"class":168},[76,1212,427],{"class":1208},[76,1214,1215],{"class":94},"}",[76,1217,1218],{"class":98},", Year: ",[76,1220,1203],{"class":94},[76,1222,745],{"class":148},[76,1224,421],{"class":1208},[76,1226,1227],{"class":168},"1",[76,1229,427],{"class":1208},[76,1231,1215],{"class":94},[76,1233,1234],{"class":98},", Month: ",[76,1236,1203],{"class":94},[76,1238,745],{"class":148},[76,1240,421],{"class":1208},[76,1242,1243],{"class":168},"2",[76,1245,427],{"class":1208},[76,1247,1215],{"class":94},[76,1249,1250],{"class":98},", Day: ",[76,1252,1203],{"class":94},[76,1254,745],{"class":148},[76,1256,421],{"class":1208},[76,1258,1259],{"class":168},"3",[76,1261,427],{"class":1208},[76,1263,1264],{"class":94},"}`\n",[76,1266,1268,1271],{"class":78,"line":1267},7,[76,1269,1270],{"class":1190},"    )",[76,1272,106],{"class":105},[76,1274,1276],{"class":78,"line":1275},8,[76,1277,1278],{"class":105},"}\n",[45,1280,1282,1283],{"id":1281},"_2-stringprototypematchall","2. ",[35,1284,1285],{},"String.prototype.matchAll",[23,1287,1288,1289,269],{},"ES2020 引入，返回可迭代对象，更简洁。",[254,1290,1291,1292,1295],{},"必须在正则上设置 ",[35,1293,1294],{},"\u002Fg"," 标志",[67,1297,1299],{"className":69,"code":1298,"language":71,"meta":72,"style":72},"const regex = \u002F(\\d{4})-(\\d{2})-(\\d{2})\u002Fg;\nconst str = \"2025-04-25, 2026-01-01\";\nfor (const match of str.matchAll(regex)) {\n    console.log(`Year: ${match[1]}, Month: ${match[2]}, Day: ${match[3]}`);\n}\n",[35,1300,1301,1345,1361,1387,1448],{"__ignoreMap":72},[76,1302,1303,1305,1307,1309,1311,1313,1315,1317,1319,1321,1323,1325,1327,1329,1331,1333,1335,1337,1339,1341,1343],{"class":78,"line":79},[76,1304,83],{"class":82},[76,1306,317],{"class":86},[76,1308,91],{"class":90},[76,1310,119],{"class":94},[76,1312,329],{"class":328},[76,1314,532],{"class":126},[76,1316,535],{"class":90},[76,1318,337],{"class":328},[76,1320,540],{"class":122},[76,1322,329],{"class":328},[76,1324,532],{"class":126},[76,1326,547],{"class":90},[76,1328,337],{"class":328},[76,1330,540],{"class":122},[76,1332,329],{"class":328},[76,1334,532],{"class":126},[76,1336,547],{"class":90},[76,1338,337],{"class":328},[76,1340,135],{"class":94},[76,1342,727],{"class":345},[76,1344,106],{"class":105},[76,1346,1347,1349,1351,1353,1355,1357,1359],{"class":78,"line":109},[76,1348,83],{"class":82},[76,1350,87],{"class":86},[76,1352,91],{"class":90},[76,1354,95],{"class":94},[76,1356,1131],{"class":98},[76,1358,102],{"class":94},[76,1360,106],{"class":105},[76,1362,1363,1366,1369,1371,1373,1376,1378,1380,1382,1385],{"class":78,"line":145},[76,1364,1365],{"class":324},"for",[76,1367,1368],{"class":148}," (",[76,1370,83],{"class":82},[76,1372,1143],{"class":86},[76,1374,1375],{"class":90}," of",[76,1377,87],{"class":148},[76,1379,127],{"class":105},[76,1381,37],{"class":154},[76,1383,1384],{"class":148},"(regex)) ",[76,1386,1177],{"class":105},[76,1388,1389,1391,1393,1395,1397,1400,1403,1405,1407,1409,1411,1413,1415,1417,1419,1421,1423,1425,1427,1429,1431,1433,1435,1437,1439,1441,1444,1446],{"class":78,"line":177},[76,1390,1183],{"class":148},[76,1392,127],{"class":105},[76,1394,155],{"class":154},[76,1396,329],{"class":1190},[76,1398,1399],{"class":94},"`",[76,1401,1402],{"class":98},"Year: ",[76,1404,1203],{"class":94},[76,1406,745],{"class":148},[76,1408,421],{"class":1208},[76,1410,1227],{"class":168},[76,1412,427],{"class":1208},[76,1414,1215],{"class":94},[76,1416,1234],{"class":98},[76,1418,1203],{"class":94},[76,1420,745],{"class":148},[76,1422,421],{"class":1208},[76,1424,1243],{"class":168},[76,1426,427],{"class":1208},[76,1428,1215],{"class":94},[76,1430,1250],{"class":98},[76,1432,1203],{"class":94},[76,1434,745],{"class":148},[76,1436,421],{"class":1208},[76,1438,1259],{"class":168},[76,1440,427],{"class":1208},[76,1442,1443],{"class":94},"}`",[76,1445,337],{"class":1190},[76,1447,106],{"class":105},[76,1449,1450],{"class":78,"line":1180},[76,1451,1278],{"class":105},[23,1453,1454,1457,1458,1460,1461,1463],{},[254,1455,1456],{},"优势","：无需手动处理 ",[35,1459,1069],{},"，且每次迭代返回的数组结构与 ",[35,1462,13],{}," 相同（包含捕获组）。",[40,1465,1467],{"id":1466},"五常见性能陷阱灾难性回溯catastrophic-backtracking","五、常见性能陷阱：灾难性回溯（Catastrophic Backtracking）",[23,1469,1470,1471,1474,1475,1478],{},"当正则表达式包含",[254,1472,1473],{},"嵌套量词","或",[254,1476,1477],{},"重叠的选择分支","时，引擎可能尝试指数级的路径，导致 CPU 飙升甚至挂起。",[45,1480,1482],{"id":1481},"_1-危险模式示例","1. 危险模式示例",[67,1484,1486],{"className":69,"code":1485,"language":71,"meta":72,"style":72},"\u002F\u002F 极其危险的表达式\nconst dangerous = \u002F^(a+)+$\u002F;\n\u002F\u002F 匹配 \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaX\" 时，会逐层回溯，耗时极长\n",[35,1487,1488,1493,1523],{"__ignoreMap":72},[76,1489,1490],{"class":78,"line":79},[76,1491,1492],{"class":141},"\u002F\u002F 极其危险的表达式\n",[76,1494,1495,1497,1500,1502,1504,1506,1508,1510,1512,1514,1516,1519,1521],{"class":78,"line":109},[76,1496,83],{"class":82},[76,1498,1499],{"class":86}," dangerous",[76,1501,91],{"class":90},[76,1503,119],{"class":94},[76,1505,977],{"class":324},[76,1507,329],{"class":328},[76,1509,27],{"class":122},[76,1511,58],{"class":90},[76,1513,337],{"class":328},[76,1515,58],{"class":90},[76,1517,1518],{"class":324},"$",[76,1520,135],{"class":94},[76,1522,106],{"class":105},[76,1524,1525],{"class":78,"line":145},[76,1526,1527],{"class":141},"\u002F\u002F 匹配 \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaX\" 时，会逐层回溯，耗时极长\n",[23,1529,1530,257],{},[254,1531,1532],{},"典型危险模式",[1534,1535,1536,1548,1560],"ul",{},[1537,1538,1539,55,1542,55,1545],"li",{},[35,1540,1541],{},"(a+)+",[35,1543,1544],{},"(a|a)+",[35,1546,1547],{},"(a*)*",[1537,1549,1550,1553,1554,1557,1558],{},[35,1551,1552],{},"(a+)*b"," 与长串不带 ",[35,1555,1556],{},"b"," 的 ",[35,1559,27],{},[1537,1561,1562,1565],{},[35,1563,1564],{},"(\\w+)+"," 配合长度较大的字符串",[45,1567,1569],{"id":1568},"_2-为什么会发生","2. 为什么会发生？",[23,1571,1572,1573,1575,1576,1578,1579,1581],{},"正则引擎（如 PCRE、JavaScript 的 V8）在进行分支选择时，会尝试所有可能路径。遇到 ",[35,1574,1541],{}," 匹配完 ",[35,1577,27],{}," 后，由于外层的 ",[35,1580,58],{}," 可以重复，回退时会产生大量排列组合。",[45,1583,1585],{"id":1584},"_3-如何避免","3. 如何避免？",[1534,1587,1588,1637,1643,1664,1670,1684,1690],{},[1537,1589,1590,1593,1594],{},[254,1591,1592],{},"使用原子分组","（JavaScript 本身不支持，但可通过前瞻模拟）\n",[67,1595,1597],{"className":69,"code":1596,"language":71,"meta":72,"style":72},"\u002F\u002F 模拟原子分组 (?=(a+))\\1\nconst safe = \u002F^(?=(a+))\\1+$\u002F;\n",[35,1598,1599,1604],{"__ignoreMap":72},[76,1600,1601],{"class":78,"line":79},[76,1602,1603],{"class":141},"\u002F\u002F 模拟原子分组 (?=(a+))\\1\n",[76,1605,1606,1608,1611,1613,1615,1617,1620,1622,1624,1627,1629,1631,1633,1635],{"class":78,"line":109},[76,1607,83],{"class":82},[76,1609,1610],{"class":86}," safe",[76,1612,91],{"class":90},[76,1614,119],{"class":94},[76,1616,977],{"class":324},[76,1618,1619],{"class":328},"(?=(",[76,1621,27],{"class":122},[76,1623,58],{"class":90},[76,1625,1626],{"class":328},"))",[76,1628,279],{"class":345},[76,1630,58],{"class":90},[76,1632,1518],{"class":324},[76,1634,135],{"class":94},[76,1636,106],{"class":105},[1537,1638,1639,1642],{},[254,1640,1641],{},"占有量词","（JS 也不支持，但可以转换为非回溯结构）",[1537,1644,1645,1648,1649],{},[254,1646,1647],{},"简化表达式","：避免不必要的嵌套量词。\n",[67,1650,1652],{"className":69,"code":1651,"language":71,"meta":72,"style":72},"\u002F\u002F 坏：\u002F^(a+)+$\u002F\n\u002F\u002F 好：\u002F^a+$\u002F（如果只需要匹配一个或多个 a）\n",[35,1653,1654,1659],{"__ignoreMap":72},[76,1655,1656],{"class":78,"line":79},[76,1657,1658],{"class":141},"\u002F\u002F 坏：\u002F^(a+)+$\u002F\n",[76,1660,1661],{"class":78,"line":109},[76,1662,1663],{"class":141},"\u002F\u002F 好：\u002F^a+$\u002F（如果只需要匹配一个或多个 a）\n",[1537,1665,1666,1669],{},[254,1667,1668],{},"限制输入长度","：在应用层面限制字符串长度。",[1537,1671,1672,1683],{},[254,1673,1674,1675,1678,1679,1682],{},"使用 ",[35,1676,1677],{},"String.prototype.search"," 或 ",[35,1680,1681],{},"indexOf"," 替代正则","（对于简单的子串匹配）。",[1537,1685,1686,1689],{},[254,1687,1688],{},"使用多个独立正则","代替一个复杂正则。",[1537,1691,1692,1695,1696,1699],{},[254,1693,1694],{},"工具检测","：使用 ",[35,1697,1698],{},"safe-regex"," 库或在线分析工具（如 regex101.com）查看回溯次数。",[45,1701,1703,1704,1707,1708,1711,1712,1715],{"id":1702},"_4-真实案例检测空格的-ss-是安全的但-aaab-匹配-aaaaaaaa无-b时可能灾难","4. 真实案例：检测空格的 ",[35,1705,1706],{},"\u002F\\s*,\\s*\u002F"," 是安全的，但 ",[35,1709,1710],{},"\u002F(a|aa)*b\u002F"," 匹配 ",[35,1713,1714],{},"aaaaaaaa...","（无 b）时可能灾难。",[40,1717,1718],{"id":1718},"总结",[600,1720,1721,1731],{},[603,1722,1723],{},[606,1724,1725,1728],{},[609,1726,1727],{},"概念",[609,1729,1730],{},"关键点",[619,1732,1733,1744,1757,1774,1787],{},[606,1734,1735,1738],{},[624,1736,1737],{},"贪婪 vs 惰性",[624,1739,1740,1741,1743],{},"默认贪婪（尽可能多），加 ",[35,1742,61],{}," 变惰性（尽可能少）",[606,1745,1746,1749],{},[624,1747,1748],{},"反向引用",[624,1750,1751,1753,1754,1756],{},[35,1752,279],{}," 引用捕获组内容；替换中 ",[35,1755,484],{}," 使用",[606,1758,1759,1762],{},[624,1760,1761],{},"前瞻\u002F后顾",[624,1763,1764,1765,55,1767,55,1769,55,1771,1773],{},"零宽断言：",[35,1766,631],{},[35,1768,644],{},[35,1770,657],{},[35,1772,670],{},"。后顾需 ES2018+",[606,1775,1776,1779],{},[624,1777,1778],{},"迭代匹配",[624,1780,1781,1783,1784,1786],{},[35,1782,13],{}," 需手动循环；",[35,1785,37],{}," 返回迭代器，更现代",[606,1788,1789,1792],{},[624,1790,1791],{},"性能陷阱",[624,1793,1794],{},"避免嵌套量词和重叠选择，警惕灾难性回溯；可用原子组模拟或简化表达式",[23,1796,1797],{},"复杂 HTML\u002FXML 解析优先用专用解析器，勿用正则勉强匹配嵌套结构。",[40,1799,1800],{"id":1800},"参考文献",[23,1802,1803],{},"以下链接在编写时均可正常访问：",[600,1805,1806,1816],{},[603,1807,1808],{},[606,1809,1810,1813],{},[609,1811,1812],{},"资料",[609,1814,1815],{},"说明",[619,1817,1818,1830,1842,1853],{},[606,1819,1820,1827],{},[624,1821,1822],{},[27,1823,1826],{"href":1824,"rel":1825},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fzh-CN\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FGlobal_Objects\u002FRegExp",[31],"MDN：RegExp",[624,1828,1829],{},"正则对象",[606,1831,1832,1839],{},[624,1833,1834],{},[27,1835,1838],{"href":1836,"rel":1837},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fzh-CN\u002Fdocs\u002FWeb\u002FJavaScript\u002FGuide\u002FRegular_expressions",[31],"MDN：Regular expressions",[624,1840,1841],{},"指南",[606,1843,1844,1851],{},[624,1845,1846],{},[27,1847,1850],{"href":1848,"rel":1849},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fzh-CN\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FGlobal_Objects\u002FString\u002FmatchAll",[31],"MDN：matchAll",[624,1852,1778],{},[606,1854,1855,1861],{},[624,1856,1857],{},[27,1858,1860],{"href":29,"rel":1859},[31],"ECMA-262：RegExp",[624,1862,1863],{},"规范（英文）",[1865,1866,1867],"style",{},"html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sQRbd, html code.shiki .sQRbd{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#DBEDFF}html pre.shiki code .stzsN, html code.shiki .stzsN{--shiki-light:#91B859;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .s-KJb, html code.shiki .s-KJb{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#DBEDFF}html pre.shiki code .sw1J6, html code.shiki .sw1J6{--shiki-light:#F76D47;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sjYin, html code.shiki .sjYin{--shiki-light:#90A4AE;--shiki-light-font-weight:inherit;--shiki-default:#22863A;--shiki-default-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sfo-9, html code.shiki .sfo-9{--shiki-light:#90A4AE;--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":72,"searchDepth":109,"depth":109,"links":1869},[1870,1874,1880,1888,1895,1902,1903],{"id":42,"depth":109,"text":43,"children":1871},[1872,1873],{"id":47,"depth":145,"text":48},{"id":183,"depth":145,"text":184},{"id":272,"depth":109,"text":273,"children":1875},[1876,1877,1878],{"id":287,"depth":145,"text":288},{"id":378,"depth":145,"text":379},{"id":480,"depth":145,"text":1879},"3. 在替换中使用 $1",{"id":594,"depth":109,"text":595,"children":1881},[1882,1883,1884,1886],{"id":676,"depth":145,"text":677},{"id":756,"depth":145,"text":757},{"id":817,"depth":145,"text":1885},"3. 正向后顾：匹配前面是 @ 的用户名",{"id":913,"depth":145,"text":1887},"4. 负向前瞻：匹配协议不是 https 的 URL",{"id":1045,"depth":109,"text":1889,"children":1890},"四、exec 与 matchAll 的迭代使用",[1891,1893],{"id":1055,"depth":145,"text":1892},"1. RegExp.prototype.exec",{"id":1281,"depth":145,"text":1894},"2. String.prototype.matchAll",{"id":1466,"depth":109,"text":1467,"children":1896},[1897,1898,1899,1900],{"id":1481,"depth":145,"text":1482},{"id":1568,"depth":145,"text":1569},{"id":1584,"depth":145,"text":1585},{"id":1702,"depth":145,"text":1901},"4. 真实案例：检测空格的 \u002F\\s*,\\s*\u002F 是安全的，但 \u002F(a|aa)*b\u002F 匹配 aaaaaaaa...（无 b）时可能灾难。",{"id":1718,"depth":109,"text":1718},{"id":1800,"depth":109,"text":1800},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fweb\u002FJs\u002Fexec","knowledge\u002Fknowledge\u002Fbooklet\u002Fweb\u002FJs\u002Fexec.md","md",{"items":1909},[1910,1914,1918,1922,1926,1930],{"path":1911,"title":1912,"description":1913,"category":10,"score":1194},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Ferror","错误处理与调试","结构化错误类型、try\u002Fcatch 与全局未捕获处理是健壮应用的基础。",{"path":1915,"title":1916,"description":1917,"category":10,"score":1194},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fdom-bom","浏览器相关 API","DOM 事件、存储、fetch、Worker、Observer 等由浏览器提供的 Web API（非 ECMAScript 核心）。HTML 结构见 标签。",{"path":1919,"title":1920,"description":1921,"category":10,"score":1194},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fperformance","性能优化","防抖\u002F节流、渲染与内存、资源预加载及引擎行为是前端性能的主要抓手。相关 CSS 见 视觉效果、Head 资源提示。",{"path":1923,"title":1924,"description":1925,"category":10,"score":1194},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fcommon","模块化与工程化","ESM、CommonJS 与打包工具（Tree Shaking、代码分割）是前端工程化的基础。入门见 JavaScript 基础 · 模块。",{"path":1927,"title":1928,"description":1929,"category":10,"score":1194},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fscope","执行模型与作用域","执行上下文与词法作用域决定变量在何处可访问、闭包如何形成，以及 var \u002F let \u002F const 的差异。语言概览见 JavaScript 基础。",{"path":1931,"title":1932,"description":1933,"category":10,"score":1194},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fmap-set","数据结构与集合增强","Map \u002F Set、WeakMap \u002F WeakSet、数组高阶方法、TypedArray 与 Symbol 等扩展了内置数据结构能力。见 语言基础。",{"series":1935,"title":71,"items":1936,"index":1267,"prev":1978,"next":1979},"booklet\u002Fweb\u002Fjs",[1937,1941,1945,1947,1951,1953,1955,1959,1960,1962,1964,1968,1972,1976],{"path":1938,"title":1939,"date":1940,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fadvanced","函数进阶","2022-10-24",{"path":1942,"title":1943,"date":1944,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fbasics","JavaScript 基础","2023-11-24",{"path":1923,"title":1924,"date":1946,"pinned":15},"2025-06-21",{"path":1948,"title":1949,"date":1950,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fdesign","设计模式","2021-10-05",{"path":1915,"title":1916,"date":1952,"pinned":15},"2025-07-10",{"path":1911,"title":1912,"date":1954,"pinned":15},"2026-06-25",{"path":1956,"title":1957,"date":1958,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fevent-loop","异步编程与事件循环","2020-03-23",{"path":7,"title":8,"date":14,"pinned":15},{"path":1931,"title":1932,"date":1961,"pinned":15},"2024-07-10",{"path":1919,"title":1920,"date":1963,"pinned":15},"2025-07-04",{"path":1965,"title":1966,"date":1967,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fprototype","原型与面向对象","2020-04-13",{"path":1969,"title":1970,"date":1971,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fproxy","代理与反射","2022-10-23",{"path":1973,"title":1974,"date":1975,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fsafe","安全","2023-06-26",{"path":1927,"title":1928,"date":1977,"pinned":15},"2025-01-29",{"path":1956,"title":1957,"date":1958,"pinned":15},{"path":1931,"title":1932,"date":1961,"pinned":15}]