[{"data":1,"prerenderedAt":11612},["ShallowReactive",2],{"page-\u002Fjavascript\u002Fjs面试部分内容摘选":3},{"id":4,"title":5,"body":6,"description":12,"extension":11603,"meta":11604,"navigation":436,"path":11608,"seo":11609,"stem":11610,"__hash__":11611},"content\u002Fjavascript\u002Fjs面试部分内容摘选.md","Js面试部分内容摘选",{"type":7,"value":8,"toc":11582},"minimark",[9,13,18,57,63,208,233,240,263,266,269,348,377,380,403,409,453,469,472,636,666,773,776,779,966,969,1018,1021,1066,1069,1149,1152,1155,1240,1246,1348,1354,1431,1443,1446,1454,1457,1513,1664,1674,1722,1725,1734,1973,1976,1987,1991,1994,1997,2000,2003,2011,2014,2020,2023,2029,2032,2124,2127,2130,2133,2139,2142,2145,2148,2155,2161,2164,2200,2203,2209,2212,2280,2283,2298,2301,2339,2342,2345,2439,2442,2445,2448,2451,2462,2465,2473,2545,2548,2678,2681,2684,2691,2697,2700,2703,3179,3182,3185,3188,3279,3282,3284,3287,3394,3397,3636,3643,3646,3656,3791,3807,3840,3843,3852,3855,3871,3874,4013,4019,4063,4076,4079,4174,6340,6343,6346,6349,6352,6355,6358,6361,6388,6394,6429,6434,6437,6579,6582,6747,6750,6858,6865,6873,6938,6941,6944,6947,7051,7260,7316,7325,7529,7532,7695,7708,7711,7714,7717,7737,7740,7844,7847,7999,8002,8123,8127,8130,8220,8223,8304,8307,8476,8479,8482,8769,8783,9078,9081,9112,9119,9473,9476,9479,9482,9485,9630,9633,9761,9764,9937,9940,9943,10017,10020,10151,10154,10268,10270,10277,10284,10295,10298,10309,10312,10315,10321,10324,10328,10331,10338,10341,10344,10353,10359,10365,10385,10389,10392,10399,10537,10540,10544,10547,10550,10897,10900,10903,11575,11578],[10,11,12],"p",{},"本笔记摘选了一些面试的时候可能会经常被问到的js问题，可以尽量背熟悉。",[14,15,17],"h3",{"id":16},"_01-02-03-嘛为什么","0.1 + 0.2 === 0.3 嘛？为什么？",[10,19,20,24,25,29,30,33,34,37,38,41,42,45,46,45,49,52,53,56],{},[21,22,23],"strong",{},"不等于。"," ",[26,27,28],"code",{},"0.1 + 0.2 === 0.3"," 返回 ",[26,31,32],{},"false","，实际结果是 ",[26,35,36],{},"0.30000000000000004","，因为 ",[21,39,40],{},"JavaScript 的数字用 IEEE 754 双精度浮点数表示","，而 ",[26,43,44],{},"0.1","、",[26,47,48],{},"0.2",[26,50,51],{},"0.3"," 这些十进制小数，在二进制里都是",[21,54,55],{},"无限循环小数","，无法精确表示。",[10,58,59,60,62],{},"把十进制的 ",[26,61,44],{}," 转成二进制：",[64,65,70],"pre",{"className":66,"code":67,"language":68,"meta":69,"style":69},"language-js shiki shiki-themes github-light github-dark","0.1 × 2 = 0.2    → 0\n0.2 × 2 = 0.4    → 0\n0.4 × 2 = 0.8    → 0\n0.8 × 2 = 1.6    → 1\n0.6 × 2 = 1.2    → 1\n0.2 × 2 = 0.4    → 0  ← 回到 0.2，开始循环\n...\n","js","",[26,71,72,100,118,137,157,176,202],{"__ignoreMap":69},[73,74,77,80,84,87,91,94,97],"span",{"class":75,"line":76},"line",1,[73,78,44],{"class":79},"sj4cs",[73,81,83],{"class":82},"sVt8B"," × ",[73,85,86],{"class":79},"2",[73,88,90],{"class":89},"szBVR"," =",[73,92,93],{"class":79}," 0.2",[73,95,96],{"class":82},"    → ",[73,98,99],{"class":79},"0\n",[73,101,103,105,107,109,111,114,116],{"class":75,"line":102},2,[73,104,48],{"class":79},[73,106,83],{"class":82},[73,108,86],{"class":79},[73,110,90],{"class":89},[73,112,113],{"class":79}," 0.4",[73,115,96],{"class":82},[73,117,99],{"class":79},[73,119,121,124,126,128,130,133,135],{"class":75,"line":120},3,[73,122,123],{"class":79},"0.4",[73,125,83],{"class":82},[73,127,86],{"class":79},[73,129,90],{"class":89},[73,131,132],{"class":79}," 0.8",[73,134,96],{"class":82},[73,136,99],{"class":79},[73,138,140,143,145,147,149,152,154],{"class":75,"line":139},4,[73,141,142],{"class":79},"0.8",[73,144,83],{"class":82},[73,146,86],{"class":79},[73,148,90],{"class":89},[73,150,151],{"class":79}," 1.6",[73,153,96],{"class":82},[73,155,156],{"class":79},"1\n",[73,158,160,163,165,167,169,172,174],{"class":75,"line":159},5,[73,161,162],{"class":79},"0.6",[73,164,83],{"class":82},[73,166,86],{"class":79},[73,168,90],{"class":89},[73,170,171],{"class":79}," 1.2",[73,173,96],{"class":82},[73,175,156],{"class":79},[73,177,179,181,183,185,187,189,191,194,197,199],{"class":75,"line":178},6,[73,180,48],{"class":79},[73,182,83],{"class":82},[73,184,86],{"class":79},[73,186,90],{"class":89},[73,188,113],{"class":79},[73,190,96],{"class":82},[73,192,193],{"class":79},"0",[73,195,196],{"class":82},"  ← 回到 ",[73,198,48],{"class":79},[73,200,201],{"class":82},"，开始循环\n",[73,203,205],{"class":75,"line":204},7,[73,206,207],{"class":89},"...\n",[10,209,210,211,214,215,218,219,222,223,225,226,228,229,232],{},"结果是 ",[26,212,213],{},"0.000110011001100110011...","，无限循环。",[21,216,217],{},"双精度浮点数只有 52 位尾数","，存不下无限循环，所以只能",[21,220,221],{},"截断或舍入","。存进去的 ",[26,224,44],{}," 已经不是精确的 ",[26,227,44],{},"，而是一个",[21,230,231],{},"非常接近但略有偏差的值","。",[10,234,235,236,239],{},"JavaScript 的设计目标之一是",[21,237,238],{},"简单","。Brendan Eich 在 1995 年设计 JS 时，选择了“一种数字类型”的方案：",[241,242,243,254,257],"ul",{},[244,245,246,247,250,251,232],"li",{},"不用区分 ",[26,248,249],{},"int"," 和 ",[26,252,253],{},"float",[244,255,256],{},"所有数字都是 64 位双精度浮点数。",[244,258,259,260,232],{},"整数的最大安全范围是 ",[26,261,262],{},"2^53 - 1",[14,264,265],{"id":265},"运行时类型检测",[10,267,268],{},"在js中，在运行时检测对象不能仅仅凭借typeof，因为typeof只能区分原始类型和对象，无法区分具体的对象类型，要判断是不是 Map 这种类型，就需要使用instanceof 或者Object.prototype.toString。",[64,270,272],{"className":66,"code":271,"language":68,"meta":69,"style":69},"typeof new Map()      \u002F\u002F \"object\"\ntypeof {}             \u002F\u002F \"object\"\ntypeof []             \u002F\u002F \"object\"\ntypeof new Date()     \u002F\u002F \"object\"\ntypeof new Set()      \u002F\u002F \"object\"\ntypeof null           \u002F\u002F \"object\"\n",[26,273,274,293,302,311,325,338],{"__ignoreMap":69},[73,275,276,279,282,286,289],{"class":75,"line":76},[73,277,278],{"class":89},"typeof",[73,280,281],{"class":89}," new",[73,283,285],{"class":284},"sScJk"," Map",[73,287,288],{"class":82},"()      ",[73,290,292],{"class":291},"sJ8bj","\u002F\u002F \"object\"\n",[73,294,295,297,300],{"class":75,"line":102},[73,296,278],{"class":89},[73,298,299],{"class":82}," {}             ",[73,301,292],{"class":291},[73,303,304,306,309],{"class":75,"line":120},[73,305,278],{"class":89},[73,307,308],{"class":82}," []             ",[73,310,292],{"class":291},[73,312,313,315,317,320,323],{"class":75,"line":139},[73,314,278],{"class":89},[73,316,281],{"class":89},[73,318,319],{"class":284}," Date",[73,321,322],{"class":82},"()     ",[73,324,292],{"class":291},[73,326,327,329,331,334,336],{"class":75,"line":159},[73,328,278],{"class":89},[73,330,281],{"class":89},[73,332,333],{"class":284}," Set",[73,335,288],{"class":82},[73,337,292],{"class":291},[73,339,340,342,345],{"class":75,"line":178},[73,341,278],{"class":89},[73,343,344],{"class":79}," null",[73,346,347],{"class":291},"           \u002F\u002F \"object\"\n",[10,349,350,351,361,362,364,365,45,368,45,371,45,374,232],{},"typeof只会返回几种字符串，分别是undefined、object、boolean、number、bigint、string、symbol、function，",[21,352,353,354,357,358,232],{},"除了 ",[26,355,356],{},"function","，所有引用类型都是 ",[26,359,360],{},"\"object\""," 所以 ",[26,363,278],{}," 无法区分 ",[26,366,367],{},"Map",[26,369,370],{},"Set",[26,372,373],{},"Array",[26,375,376],{},"Date",[10,378,379],{},"instanceof检查的是原型链，也就是对象的原型链上有没有这个构造函数的prototype。",[64,381,383],{"className":66,"code":382,"language":68,"meta":69,"style":69},"new Map() instanceof Map  \u002F\u002F true\n",[26,384,385],{"__ignoreMap":69},[73,386,387,390,392,395,398,400],{"class":75,"line":76},[73,388,389],{"class":89},"new",[73,391,285],{"class":284},[73,393,394],{"class":82},"() ",[73,396,397],{"class":89},"instanceof",[73,399,285],{"class":284},[73,401,402],{"class":291},"  \u002F\u002F true\n",[10,404,405,408],{},[21,406,407],{},"跨 iframe \u002F 跨 window 失效"," ：",[64,410,412],{"className":66,"code":411,"language":68,"meta":69,"style":69},"\u002F\u002F iframe 里的 Map\nconst iframeMap = iframe.contentWindow.Map\n\nnew Map() instanceof iframeMap  \u002F\u002F false ❌\n",[26,413,414,419,432,438],{"__ignoreMap":69},[73,415,416],{"class":75,"line":76},[73,417,418],{"class":291},"\u002F\u002F iframe 里的 Map\n",[73,420,421,424,427,429],{"class":75,"line":102},[73,422,423],{"class":89},"const",[73,425,426],{"class":79}," iframeMap",[73,428,90],{"class":89},[73,430,431],{"class":82}," iframe.contentWindow.Map\n",[73,433,434],{"class":75,"line":120},[73,435,437],{"emptyLinePlaceholder":436},true,"\n",[73,439,440,442,444,446,448,450],{"class":75,"line":139},[73,441,389],{"class":89},[73,443,285],{"class":284},[73,445,394],{"class":82},[73,447,397],{"class":89},[73,449,426],{"class":284},[73,451,452],{"class":291},"  \u002F\u002F false ❌\n",[10,454,455,456,458,459,462,463],{},"因为 iframe 有自己的 ",[26,457,367],{}," 构造函数，",[26,460,461],{},"Map.prototype"," 不是同一个对象。",[21,464,465,466,468],{},"原型链上找的是当前 window 的 ",[26,467,461],{},"，不是 iframe 的。",[10,470,471],{},"更加可靠的是 使用Object.prototype.toString方法：",[64,473,475],{"className":66,"code":474,"language":68,"meta":69,"style":69},"Object.prototype.toString.call(new Map())      \u002F\u002F \"[object Map]\"\nObject.prototype.toString.call(new Set())      \u002F\u002F \"[object Set]\"\nObject.prototype.toString.call([])             \u002F\u002F \"[object Array]\"\nObject.prototype.toString.call(new Date())     \u002F\u002F \"[object Date]\"\nObject.prototype.toString.call({})             \u002F\u002F \"[object Object]\"\nObject.prototype.toString.call(null)           \u002F\u002F \"[object Null]\"\nObject.prototype.toString.call(undefined)      \u002F\u002F \"[object Undefined]\"\n",[26,476,477,507,530,548,572,590,613],{"__ignoreMap":69},[73,478,479,482,485,488,491,494,497,499,501,504],{"class":75,"line":76},[73,480,481],{"class":79},"Object",[73,483,484],{"class":82},".",[73,486,487],{"class":79},"prototype",[73,489,490],{"class":82},".toString.",[73,492,493],{"class":284},"call",[73,495,496],{"class":82},"(",[73,498,389],{"class":89},[73,500,285],{"class":284},[73,502,503],{"class":82},"())      ",[73,505,506],{"class":291},"\u002F\u002F \"[object Map]\"\n",[73,508,509,511,513,515,517,519,521,523,525,527],{"class":75,"line":102},[73,510,481],{"class":79},[73,512,484],{"class":82},[73,514,487],{"class":79},[73,516,490],{"class":82},[73,518,493],{"class":284},[73,520,496],{"class":82},[73,522,389],{"class":89},[73,524,333],{"class":284},[73,526,503],{"class":82},[73,528,529],{"class":291},"\u002F\u002F \"[object Set]\"\n",[73,531,532,534,536,538,540,542,545],{"class":75,"line":120},[73,533,481],{"class":79},[73,535,484],{"class":82},[73,537,487],{"class":79},[73,539,490],{"class":82},[73,541,493],{"class":284},[73,543,544],{"class":82},"([])             ",[73,546,547],{"class":291},"\u002F\u002F \"[object Array]\"\n",[73,549,550,552,554,556,558,560,562,564,566,569],{"class":75,"line":139},[73,551,481],{"class":79},[73,553,484],{"class":82},[73,555,487],{"class":79},[73,557,490],{"class":82},[73,559,493],{"class":284},[73,561,496],{"class":82},[73,563,389],{"class":89},[73,565,319],{"class":284},[73,567,568],{"class":82},"())     ",[73,570,571],{"class":291},"\u002F\u002F \"[object Date]\"\n",[73,573,574,576,578,580,582,584,587],{"class":75,"line":159},[73,575,481],{"class":79},[73,577,484],{"class":82},[73,579,487],{"class":79},[73,581,490],{"class":82},[73,583,493],{"class":284},[73,585,586],{"class":82},"({})             ",[73,588,589],{"class":291},"\u002F\u002F \"[object Object]\"\n",[73,591,592,594,596,598,600,602,604,607,610],{"class":75,"line":178},[73,593,481],{"class":79},[73,595,484],{"class":82},[73,597,487],{"class":79},[73,599,490],{"class":82},[73,601,493],{"class":284},[73,603,496],{"class":82},[73,605,606],{"class":79},"null",[73,608,609],{"class":82},")           ",[73,611,612],{"class":291},"\u002F\u002F \"[object Null]\"\n",[73,614,615,617,619,621,623,625,627,630,633],{"class":75,"line":204},[73,616,481],{"class":79},[73,618,484],{"class":82},[73,620,487],{"class":79},[73,622,490],{"class":82},[73,624,493],{"class":284},[73,626,496],{"class":82},[73,628,629],{"class":79},"undefined",[73,631,632],{"class":82},")      ",[73,634,635],{"class":291},"\u002F\u002F \"[object Undefined]\"\n",[10,637,638,641,642,645,646,649,650,232,653,656,657,659,660,663,664,232],{},[26,639,640],{},"Object.prototype.toString"," 会读取对象内部的 ",[26,643,644],{},"[[Class]]"," 或 ",[26,647,648],{},"Symbol.toStringTag"," 属性，返回 ",[26,651,652],{},"[object Xxx]",[21,654,655],{},"跨 iframe 有效"," ， 因为 ",[26,658,644],{}," 是引擎内部的标记，不受 window 隔离影响。",[21,661,662],{},"不受原型链修改影响","：因为不依赖 ",[26,665,487],{},[64,667,669],{"className":66,"code":668,"language":68,"meta":69,"style":69},"export function getType(value: unknown) {\n  return Object.prototype.toString.call(value).slice(8, -1).toLocaleLowerCase()\n}\n\nconsole.log(getType(new Map()))\n\n",[26,670,671,697,742,747,751],{"__ignoreMap":69},[73,672,673,676,679,682,684,688,691,694],{"class":75,"line":76},[73,674,675],{"class":89},"export",[73,677,678],{"class":89}," function",[73,680,681],{"class":284}," getType",[73,683,496],{"class":82},[73,685,687],{"class":686},"s4XuR","value",[73,689,690],{"class":89},":",[73,692,693],{"class":79}," unknown",[73,695,696],{"class":82},") {\n",[73,698,699,702,705,707,709,711,713,716,719,721,724,727,730,733,736,739],{"class":75,"line":102},[73,700,701],{"class":89},"  return",[73,703,704],{"class":79}," Object",[73,706,484],{"class":82},[73,708,487],{"class":79},[73,710,490],{"class":82},[73,712,493],{"class":284},[73,714,715],{"class":82},"(value).",[73,717,718],{"class":284},"slice",[73,720,496],{"class":82},[73,722,723],{"class":79},"8",[73,725,726],{"class":82},", ",[73,728,729],{"class":89},"-",[73,731,732],{"class":79},"1",[73,734,735],{"class":82},").",[73,737,738],{"class":284},"toLocaleLowerCase",[73,740,741],{"class":82},"()\n",[73,743,744],{"class":75,"line":120},[73,745,746],{"class":82},"}\n",[73,748,749],{"class":75,"line":139},[73,750,437],{"emptyLinePlaceholder":436},[73,752,753,756,759,761,764,766,768,770],{"class":75,"line":159},[73,754,755],{"class":82},"console.",[73,757,758],{"class":284},"log",[73,760,496],{"class":82},[73,762,763],{"class":284},"getType",[73,765,496],{"class":82},[73,767,389],{"class":89},[73,769,285],{"class":284},[73,771,772],{"class":82},"()))\n",[14,774,775],{"id":775},"脚本和模块",[10,777,778],{},"在JS中，如果没有export，js就会被当成脚本，但是有export就会当做模块，这是 JavaScript 的一个核心区别。",[780,781,782,798],"table",{},[783,784,785],"thead",{},[786,787,788,792,795],"tr",{},[789,790,791],"th",{},"维度",[789,793,794],{},"Script",[789,796,797],{},"Module（ESM）",[799,800,801,825,845,858,878,895,908,921,937,951],"tbody",{},[786,802,803,809,818],{},[804,805,806],"td",{},[21,807,808],{},"触发条件",[804,810,811,812,815,816],{},"没有 ",[26,813,814],{},"import"," \u002F ",[26,817,675],{},[804,819,820,821,815,823],{},"有顶层 ",[26,822,814],{},[26,824,675],{},[786,826,827,835,840],{},[804,828,829],{},[21,830,831,834],{},[26,832,833],{},"\u003Cscript>"," 标签",[804,836,837,839],{},[26,838,833],{},"（默认）",[804,841,842],{},[26,843,844],{},"\u003Cscript type=\"module\">",[786,846,847,852,855],{},[804,848,849],{},[21,850,851],{},"作用域",[804,853,854],{},"全局",[804,856,857],{},"模块级（文件作用域）",[786,859,860,868,874],{},[804,861,862],{},[21,863,864,865],{},"顶层 ",[26,866,867],{},"this",[804,869,870,873],{},[26,871,872],{},"window","（浏览器）",[804,875,876],{},[26,877,629],{},[786,879,880,885,890],{},[804,881,882],{},[21,883,884],{},"变量共享",[804,886,887,888],{},"全局变量挂到 ",[26,889,872],{},[804,891,892,893],{},"不挂到 ",[26,894,872],{},[786,896,897,902,905],{},[804,898,899],{},[21,900,901],{},"变量提升",[804,903,904],{},"有",[804,906,907],{},"有，但有 TDZ",[786,909,910,915,918],{},[804,911,912],{},[21,913,914],{},"严格模式",[804,916,917],{},"默认非严格",[804,919,920],{},"默认严格",[786,922,923,931,934],{},[804,924,925],{},[21,926,927,930],{},[26,928,929],{},"await"," 顶层",[804,932,933],{},"不允许",[804,935,936],{},"允许",[786,938,939,947,949],{},[804,940,941],{},[21,942,943,946],{},[26,944,945],{},"import()"," 动态导入",[804,948,936],{},[804,950,936],{},[786,952,953,961,963],{},[804,954,955],{},[21,956,957,960],{},[26,958,959],{},".js"," 默认解析",[804,962,794],{},[804,964,965],{},"Module",[10,967,968],{},"script",[64,970,972],{"className":66,"code":971,"language":68,"meta":69,"style":69},"\u002F\u002F a.js\nvar foo = 'hello'  \u002F\u002F 挂到 window.foo\n\n\u002F\u002F b.js\nconsole.log(foo)   \u002F\u002F \"hello\"，能访问\n",[26,973,974,979,997,1001,1006],{"__ignoreMap":69},[73,975,976],{"class":75,"line":76},[73,977,978],{"class":291},"\u002F\u002F a.js\n",[73,980,981,984,987,990,994],{"class":75,"line":102},[73,982,983],{"class":89},"var",[73,985,986],{"class":82}," foo ",[73,988,989],{"class":89},"=",[73,991,993],{"class":992},"sZZnC"," 'hello'",[73,995,996],{"class":291},"  \u002F\u002F 挂到 window.foo\n",[73,998,999],{"class":75,"line":120},[73,1000,437],{"emptyLinePlaceholder":436},[73,1002,1003],{"class":75,"line":139},[73,1004,1005],{"class":291},"\u002F\u002F b.js\n",[73,1007,1008,1010,1012,1015],{"class":75,"line":159},[73,1009,755],{"class":82},[73,1011,758],{"class":284},[73,1013,1014],{"class":82},"(foo)   ",[73,1016,1017],{"class":291},"\u002F\u002F \"hello\"，能访问\n",[10,1019,1020],{},"module",[64,1022,1024],{"className":66,"code":1023,"language":68,"meta":69,"style":69},"\u002F\u002F a.js\nexport const foo = 'hello'  \u002F\u002F 模块级，不挂到 window\n\n\u002F\u002F b.js\nconsole.log(foo)   \u002F\u002F ❌ ReferenceError，访问不到\n",[26,1025,1026,1030,1047,1051,1055],{"__ignoreMap":69},[73,1027,1028],{"class":75,"line":76},[73,1029,978],{"class":291},[73,1031,1032,1034,1037,1040,1042,1044],{"class":75,"line":102},[73,1033,675],{"class":89},[73,1035,1036],{"class":89}," const",[73,1038,1039],{"class":79}," foo",[73,1041,90],{"class":89},[73,1043,993],{"class":992},[73,1045,1046],{"class":291},"  \u002F\u002F 模块级，不挂到 window\n",[73,1048,1049],{"class":75,"line":120},[73,1050,437],{"emptyLinePlaceholder":436},[73,1052,1053],{"class":75,"line":139},[73,1054,1005],{"class":291},[73,1056,1057,1059,1061,1063],{"class":75,"line":159},[73,1058,755],{"class":82},[73,1060,758],{"class":284},[73,1062,1014],{"class":82},[73,1064,1065],{"class":291},"\u002F\u002F ❌ ReferenceError，访问不到\n",[10,1067,1068],{},"判断一个文件是script还是module可以看有没有import\u002Fexport。也可以看script标签：",[64,1070,1072],{"className":66,"code":1071,"language":68,"meta":69,"style":69},"\u003C!-- Script -->\n\u003Cscript src=\"script.js\">\u003C\u002Fscript>\n\n\u003C!-- Module -->\n\u003Cscript type=\"module\" src=\"module.js\">\u003C\u002Fscript>\n",[26,1073,1074,1085,1109,1113,1122],{"__ignoreMap":69},[73,1075,1076,1079,1082],{"class":75,"line":76},[73,1077,1078],{"class":89},"\u003C!--",[73,1080,1081],{"class":82}," Script ",[73,1083,1084],{"class":89},"-->\n",[73,1086,1087,1090,1093,1096,1098,1101,1104,1106],{"class":75,"line":102},[73,1088,1089],{"class":82},"\u003C",[73,1091,968],{"class":1092},"s9eBZ",[73,1094,1095],{"class":284}," src",[73,1097,989],{"class":89},[73,1099,1100],{"class":992},"\"script.js\"",[73,1102,1103],{"class":82},">\u003C\u002F",[73,1105,968],{"class":1092},[73,1107,1108],{"class":82},">\n",[73,1110,1111],{"class":75,"line":120},[73,1112,437],{"emptyLinePlaceholder":436},[73,1114,1115,1117,1120],{"class":75,"line":139},[73,1116,1078],{"class":89},[73,1118,1119],{"class":82}," Module ",[73,1121,1084],{"class":89},[73,1123,1124,1126,1128,1131,1133,1136,1138,1140,1143,1145,1147],{"class":75,"line":159},[73,1125,1089],{"class":82},[73,1127,968],{"class":1092},[73,1129,1130],{"class":284}," type",[73,1132,989],{"class":89},[73,1134,1135],{"class":992},"\"module\"",[73,1137,1095],{"class":284},[73,1139,989],{"class":89},[73,1141,1142],{"class":992},"\"module.js\"",[73,1144,1103],{"class":82},[73,1146,968],{"class":1092},[73,1148,1108],{"class":82},[10,1150,1151],{},"也可以看pacakge.json里的type字段，type:module 中.js文件默认当做module，type:commonjs或者没有.js文件默认当做cmj，mjs当做module，cjs当做cjs.",[10,1153,1154],{},"还有一点，我们都知道import esm是异步方法，我们可以看看@types+node的类型定义层面，",[64,1156,1160],{"className":1157,"code":1158,"language":1159,"meta":69,"style":69},"language-ts shiki shiki-themes github-light github-dark","            \u002F**\n             * The absolute `file:` URL of the module.\n             *\n             * This is defined exactly the same as it is in browsers providing the URL of the\n             * current module file.\n             *\n             * This enables useful patterns such as relative file loading:\n             *\n             * ```js\n             * import { readFileSync } from 'node:fs';\n             * const buffer = readFileSync(new URL('.\u002Fdata.proto', import.meta.url));\n             * ```\n             *\u002F\n            url: string;\n","ts",[26,1161,1162,1167,1172,1177,1182,1187,1191,1196,1201,1207,1213,1219,1225,1231],{"__ignoreMap":69},[73,1163,1164],{"class":75,"line":76},[73,1165,1166],{"class":291},"            \u002F**\n",[73,1168,1169],{"class":75,"line":102},[73,1170,1171],{"class":291},"             * The absolute `file:` URL of the module.\n",[73,1173,1174],{"class":75,"line":120},[73,1175,1176],{"class":291},"             *\n",[73,1178,1179],{"class":75,"line":139},[73,1180,1181],{"class":291},"             * This is defined exactly the same as it is in browsers providing the URL of the\n",[73,1183,1184],{"class":75,"line":159},[73,1185,1186],{"class":291},"             * current module file.\n",[73,1188,1189],{"class":75,"line":178},[73,1190,1176],{"class":291},[73,1192,1193],{"class":75,"line":204},[73,1194,1195],{"class":291},"             * This enables useful patterns such as relative file loading:\n",[73,1197,1199],{"class":75,"line":1198},8,[73,1200,1176],{"class":291},[73,1202,1204],{"class":75,"line":1203},9,[73,1205,1206],{"class":291},"             * ```js\n",[73,1208,1210],{"class":75,"line":1209},10,[73,1211,1212],{"class":291},"             * import { readFileSync } from 'node:fs';\n",[73,1214,1216],{"class":75,"line":1215},11,[73,1217,1218],{"class":291},"             * const buffer = readFileSync(new URL('.\u002Fdata.proto', import.meta.url));\n",[73,1220,1222],{"class":75,"line":1221},12,[73,1223,1224],{"class":291},"             * ```\n",[73,1226,1228],{"class":75,"line":1227},13,[73,1229,1230],{"class":291},"             *\u002F\n",[73,1232,1234,1237],{"class":75,"line":1233},14,[73,1235,1236],{"class":284},"            url",[73,1238,1239],{"class":82},": string;\n",[10,1241,1242,1245],{},[26,1243,1244],{},"import.meta"," 在 TypeScript 里的类型定义分几层：",[780,1247,1248,1258],{},[783,1249,1250],{},[786,1251,1252,1255],{},[789,1253,1254],{},"类型定义来源",[789,1256,1257],{},"提供什么",[799,1259,1260,1277,1292,1309,1330],{},[786,1261,1262,1271],{},[804,1263,1264],{},[21,1265,1266,1267,1270],{},"TypeScript 内置（",[26,1268,1269],{},"lib.es5.d.ts","）",[804,1272,1273,1276],{},[26,1274,1275],{},"ImportMeta"," 空接口",[786,1278,1279,1286],{},[804,1280,1281],{},[21,1282,1283],{},[26,1284,1285],{},"lib.dom.d.ts",[804,1287,1288,1291],{},[26,1289,1290],{},"import.meta.url","（浏览器环境）",[786,1293,1294,1301],{},[804,1295,1296],{},[21,1297,1298],{},[26,1299,1300],{},"@types\u002Fnode",[804,1302,1303,45,1305,1308],{},[26,1304,1290],{},[26,1306,1307],{},"import.meta.resolve","（Node 环境）",[786,1310,1311,1319],{},[804,1312,1313],{},[21,1314,1315,1316,1270],{},"Vite（",[26,1317,1318],{},"vite\u002Fclient",[804,1320,1321,45,1324,45,1327],{},[26,1322,1323],{},"import.meta.env",[26,1325,1326],{},"import.meta.hot",[26,1328,1329],{},"import.meta.glob",[786,1331,1332,1337],{},[804,1333,1334],{},[21,1335,1336],{},"Nuxt",[804,1338,1339,45,1342,45,1345],{},[26,1340,1341],{},"import.meta.client",[26,1343,1344],{},"import.meta.server",[26,1346,1347],{},"import.meta.dev",[10,1349,1350,1351,1353],{},"我们可以看看Vite \u002F Nuxt 对 ",[26,1352,1244],{}," 的类型扩展：",[64,1355,1357],{"className":1157,"code":1356,"language":1159,"meta":69,"style":69},"interface ImportMeta {\n    browser: boolean;\n    client: boolean;\n    dev: boolean;\n    server: boolean;\n    test: boolean;\n}\n",[26,1358,1359,1370,1383,1394,1405,1416,1427],{"__ignoreMap":69},[73,1360,1361,1364,1367],{"class":75,"line":76},[73,1362,1363],{"class":89},"interface",[73,1365,1366],{"class":284}," ImportMeta",[73,1368,1369],{"class":82}," {\n",[73,1371,1372,1375,1377,1380],{"class":75,"line":102},[73,1373,1374],{"class":686},"    browser",[73,1376,690],{"class":89},[73,1378,1379],{"class":79}," boolean",[73,1381,1382],{"class":82},";\n",[73,1384,1385,1388,1390,1392],{"class":75,"line":120},[73,1386,1387],{"class":686},"    client",[73,1389,690],{"class":89},[73,1391,1379],{"class":79},[73,1393,1382],{"class":82},[73,1395,1396,1399,1401,1403],{"class":75,"line":139},[73,1397,1398],{"class":686},"    dev",[73,1400,690],{"class":89},[73,1402,1379],{"class":79},[73,1404,1382],{"class":82},[73,1406,1407,1410,1412,1414],{"class":75,"line":159},[73,1408,1409],{"class":686},"    server",[73,1411,690],{"class":89},[73,1413,1379],{"class":79},[73,1415,1382],{"class":82},[73,1417,1418,1421,1423,1425],{"class":75,"line":178},[73,1419,1420],{"class":686},"    test",[73,1422,690],{"class":89},[73,1424,1379],{"class":79},[73,1426,1382],{"class":82},[73,1428,1429],{"class":75,"line":204},[73,1430,746],{"class":82},[10,1432,1433,1434,1436,1437,645,1440,1442],{},"这些用来标记代码运行在什么环境。Vite 在构建时把 ",[26,1435,1341],{}," 替换成 ",[26,1438,1439],{},"true",[26,1441,32],{},"，运行时零开销。",[14,1444,1445],{"id":1445},"await和事件循环",[10,1447,1448,1449],{},"我们一直说await是等待任务完成，但是原理模型是需要了解的，",[21,1450,1451,1453],{},[26,1452,929],{}," 不是“阻塞”，它是“挂起当前函数，让出线程”。",[10,1455,1456],{},"同步阻塞说的类似于fs.readFileSync这样的node环境方法，线程卡在这里，什么都做不了，await会让当前函数暂停，让线程去做别的事情，也叫做suspending：",[64,1458,1460],{"className":66,"code":1459,"language":68,"meta":69,"style":69},"\u002F\u002F 异步挂起\nconst data = await fs.readFile('a.txt')  \u002F\u002F 当前函数暂停，线程去处理其他任务\nconsole.log('done')                      \u002F\u002F 等数据到了，函数恢复执行\n",[26,1461,1462,1467,1496],{"__ignoreMap":69},[73,1463,1464],{"class":75,"line":76},[73,1465,1466],{"class":291},"\u002F\u002F 异步挂起\n",[73,1468,1469,1471,1474,1476,1479,1482,1485,1487,1490,1493],{"class":75,"line":102},[73,1470,423],{"class":89},[73,1472,1473],{"class":79}," data",[73,1475,90],{"class":89},[73,1477,1478],{"class":89}," await",[73,1480,1481],{"class":82}," fs.",[73,1483,1484],{"class":284},"readFile",[73,1486,496],{"class":82},[73,1488,1489],{"class":992},"'a.txt'",[73,1491,1492],{"class":82},")  ",[73,1494,1495],{"class":291},"\u002F\u002F 当前函数暂停，线程去处理其他任务\n",[73,1497,1498,1500,1502,1504,1507,1510],{"class":75,"line":120},[73,1499,755],{"class":82},[73,1501,758],{"class":284},[73,1503,496],{"class":82},[73,1505,1506],{"class":992},"'done'",[73,1508,1509],{"class":82},")                      ",[73,1511,1512],{"class":291},"\u002F\u002F 等数据到了，函数恢复执行\n",[64,1514,1516],{"className":66,"code":1515,"language":68,"meta":69,"style":69},"async function fetchData() {\n  console.log('1')\n  const data = await fetch('\u002Fapi')  \u002F\u002F 挂起点\n  console.log('2')\n}\n\nfetchData()\nconsole.log('3')\n\n1. 执行 fetchData，打印 \"1\"\n2. 遇到 await，fetchData 挂起，返回一个 Promise\n3. 主线程继续执行，打印 \"3\"\n4. fetch 完成后，fetchData 恢复，打印 \"2\"\n",[26,1517,1518,1531,1546,1570,1583,1587,1591,1598,1611,1615,1626,1642,1653],{"__ignoreMap":69},[73,1519,1520,1523,1525,1528],{"class":75,"line":76},[73,1521,1522],{"class":89},"async",[73,1524,678],{"class":89},[73,1526,1527],{"class":284}," fetchData",[73,1529,1530],{"class":82},"() {\n",[73,1532,1533,1536,1538,1540,1543],{"class":75,"line":102},[73,1534,1535],{"class":82},"  console.",[73,1537,758],{"class":284},[73,1539,496],{"class":82},[73,1541,1542],{"class":992},"'1'",[73,1544,1545],{"class":82},")\n",[73,1547,1548,1551,1553,1555,1557,1560,1562,1565,1567],{"class":75,"line":120},[73,1549,1550],{"class":89},"  const",[73,1552,1473],{"class":79},[73,1554,90],{"class":89},[73,1556,1478],{"class":89},[73,1558,1559],{"class":284}," fetch",[73,1561,496],{"class":82},[73,1563,1564],{"class":992},"'\u002Fapi'",[73,1566,1492],{"class":82},[73,1568,1569],{"class":291},"\u002F\u002F 挂起点\n",[73,1571,1572,1574,1576,1578,1581],{"class":75,"line":139},[73,1573,1535],{"class":82},[73,1575,758],{"class":284},[73,1577,496],{"class":82},[73,1579,1580],{"class":992},"'2'",[73,1582,1545],{"class":82},[73,1584,1585],{"class":75,"line":159},[73,1586,746],{"class":82},[73,1588,1589],{"class":75,"line":178},[73,1590,437],{"emptyLinePlaceholder":436},[73,1592,1593,1596],{"class":75,"line":204},[73,1594,1595],{"class":284},"fetchData",[73,1597,741],{"class":82},[73,1599,1600,1602,1604,1606,1609],{"class":75,"line":1198},[73,1601,755],{"class":82},[73,1603,758],{"class":284},[73,1605,496],{"class":82},[73,1607,1608],{"class":992},"'3'",[73,1610,1545],{"class":82},[73,1612,1613],{"class":75,"line":1203},[73,1614,437],{"emptyLinePlaceholder":436},[73,1616,1617,1620,1623],{"class":75,"line":1209},[73,1618,1619],{"class":79},"1.",[73,1621,1622],{"class":82}," 执行 fetchData，打印 ",[73,1624,1625],{"class":992},"\"1\"\n",[73,1627,1628,1631,1634,1636,1639],{"class":75,"line":1215},[73,1629,1630],{"class":79},"2.",[73,1632,1633],{"class":82}," 遇到 ",[73,1635,929],{"class":89},[73,1637,1638],{"class":82},"，fetchData 挂起，返回一个 ",[73,1640,1641],{"class":79},"Promise\n",[73,1643,1644,1647,1650],{"class":75,"line":1221},[73,1645,1646],{"class":79},"3.",[73,1648,1649],{"class":82}," 主线程继续执行，打印 ",[73,1651,1652],{"class":992},"\"3\"\n",[73,1654,1655,1658,1661],{"class":75,"line":1227},[73,1656,1657],{"class":79},"4.",[73,1659,1660],{"class":82}," fetch 完成后，fetchData 恢复，打印 ",[73,1662,1663],{"class":992},"\"2\"\n",[10,1665,1666,1667,1670,1671],{},"我们知道await挂起的是async方法，不是整个程序，await之后的代码会被注册为Promise的.then回调，这个回调进入的是微任务队列，而不是宏任务队列。\n",[21,1668,1669],{},"微任务队列","和",[21,1672,1673],{},"宏任务队列",[780,1675,1676,1689],{},[783,1677,1678],{},[786,1679,1680,1683,1686],{},[789,1681,1682],{},"队列",[789,1684,1685],{},"存放内容",[789,1687,1688],{},"执行时机",[799,1690,1691,1706],{},[786,1692,1693,1697,1700],{},[804,1694,1695],{},[21,1696,1669],{},[804,1698,1699],{},"Promise.then、await 恢复、MutationObserver",[804,1701,1702,1703],{},"每个宏任务结束后，",[21,1704,1705],{},"清空所有微任务",[786,1707,1708,1712,1715],{},[804,1709,1710],{},[21,1711,1673],{},[804,1713,1714],{},"setTimeout、setInterval、I\u002FO、UI 渲染",[804,1716,1717,1718,1721],{},"每轮事件循环取",[21,1719,1720],{},"一个","宏任务",[10,1723,1724],{},"我们知道事件的循环是： 执行调用栈里的同步代码，调用栈清空，开始执行微任务队列，微任务队列清空，执行下一个宏任务，然后继续调用栈清空。",[10,1726,1727,1729,1730,1733],{},[26,1728,929],{}," 恢复是微任务，所以",[21,1731,1732],{},"会在调用栈清空后立刻执行","，不会等 UI 渲染或 setTimeout。",[64,1735,1737],{"className":66,"code":1736,"language":68,"meta":69,"style":69},"console.log('A')\n\nsetTimeout(() => console.log('B'), 0)  \u002F\u002F 宏任务\n\nPromise.resolve().then(() => console.log('C'))  \u002F\u002F 微任务\n\nasync function foo() {\n  console.log('D')\n  await null  \u002F\u002F 挂起\n  console.log('E')  \u002F\u002F 微任务\n}\n\nfoo()\n\nconsole.log('F')\n\nA          ← 同步\nD          ← 同步\nF          ← 同步\nC          ← 微任务\nE          ← 微任务（await 恢复）\nB          ← 宏任务\n",[26,1738,1739,1752,1756,1787,1791,1826,1830,1840,1853,1863,1878,1882,1886,1893,1897,1911,1916,1925,1933,1941,1950,1964],{"__ignoreMap":69},[73,1740,1741,1743,1745,1747,1750],{"class":75,"line":76},[73,1742,755],{"class":82},[73,1744,758],{"class":284},[73,1746,496],{"class":82},[73,1748,1749],{"class":992},"'A'",[73,1751,1545],{"class":82},[73,1753,1754],{"class":75,"line":102},[73,1755,437],{"emptyLinePlaceholder":436},[73,1757,1758,1761,1764,1767,1770,1772,1774,1777,1780,1782,1784],{"class":75,"line":120},[73,1759,1760],{"class":284},"setTimeout",[73,1762,1763],{"class":82},"(() ",[73,1765,1766],{"class":89},"=>",[73,1768,1769],{"class":82}," console.",[73,1771,758],{"class":284},[73,1773,496],{"class":82},[73,1775,1776],{"class":992},"'B'",[73,1778,1779],{"class":82},"), ",[73,1781,193],{"class":79},[73,1783,1492],{"class":82},[73,1785,1786],{"class":291},"\u002F\u002F 宏任务\n",[73,1788,1789],{"class":75,"line":139},[73,1790,437],{"emptyLinePlaceholder":436},[73,1792,1793,1796,1798,1801,1804,1807,1809,1811,1813,1815,1817,1820,1823],{"class":75,"line":159},[73,1794,1795],{"class":79},"Promise",[73,1797,484],{"class":82},[73,1799,1800],{"class":284},"resolve",[73,1802,1803],{"class":82},"().",[73,1805,1806],{"class":284},"then",[73,1808,1763],{"class":82},[73,1810,1766],{"class":89},[73,1812,1769],{"class":82},[73,1814,758],{"class":284},[73,1816,496],{"class":82},[73,1818,1819],{"class":992},"'C'",[73,1821,1822],{"class":82},"))  ",[73,1824,1825],{"class":291},"\u002F\u002F 微任务\n",[73,1827,1828],{"class":75,"line":178},[73,1829,437],{"emptyLinePlaceholder":436},[73,1831,1832,1834,1836,1838],{"class":75,"line":204},[73,1833,1522],{"class":89},[73,1835,678],{"class":89},[73,1837,1039],{"class":284},[73,1839,1530],{"class":82},[73,1841,1842,1844,1846,1848,1851],{"class":75,"line":1198},[73,1843,1535],{"class":82},[73,1845,758],{"class":284},[73,1847,496],{"class":82},[73,1849,1850],{"class":992},"'D'",[73,1852,1545],{"class":82},[73,1854,1855,1858,1860],{"class":75,"line":1203},[73,1856,1857],{"class":89},"  await",[73,1859,344],{"class":79},[73,1861,1862],{"class":291},"  \u002F\u002F 挂起\n",[73,1864,1865,1867,1869,1871,1874,1876],{"class":75,"line":1209},[73,1866,1535],{"class":82},[73,1868,758],{"class":284},[73,1870,496],{"class":82},[73,1872,1873],{"class":992},"'E'",[73,1875,1492],{"class":82},[73,1877,1825],{"class":291},[73,1879,1880],{"class":75,"line":1215},[73,1881,746],{"class":82},[73,1883,1884],{"class":75,"line":1221},[73,1885,437],{"emptyLinePlaceholder":436},[73,1887,1888,1891],{"class":75,"line":1227},[73,1889,1890],{"class":284},"foo",[73,1892,741],{"class":82},[73,1894,1895],{"class":75,"line":1233},[73,1896,437],{"emptyLinePlaceholder":436},[73,1898,1900,1902,1904,1906,1909],{"class":75,"line":1899},15,[73,1901,755],{"class":82},[73,1903,758],{"class":284},[73,1905,496],{"class":82},[73,1907,1908],{"class":992},"'F'",[73,1910,1545],{"class":82},[73,1912,1914],{"class":75,"line":1913},16,[73,1915,437],{"emptyLinePlaceholder":436},[73,1917,1919,1922],{"class":75,"line":1918},17,[73,1920,1921],{"class":79},"A",[73,1923,1924],{"class":82},"          ← 同步\n",[73,1926,1928,1931],{"class":75,"line":1927},18,[73,1929,1930],{"class":79},"D",[73,1932,1924],{"class":82},[73,1934,1936,1939],{"class":75,"line":1935},19,[73,1937,1938],{"class":79},"F",[73,1940,1924],{"class":82},[73,1942,1944,1947],{"class":75,"line":1943},20,[73,1945,1946],{"class":79},"C",[73,1948,1949],{"class":82},"          ← 微任务\n",[73,1951,1953,1956,1959,1961],{"class":75,"line":1952},21,[73,1954,1955],{"class":79},"E",[73,1957,1958],{"class":82},"          ← 微任务（",[73,1960,929],{"class":89},[73,1962,1963],{"class":82}," 恢复）\n",[73,1965,1967,1970],{"class":75,"line":1966},22,[73,1968,1969],{"class":79},"B",[73,1971,1972],{"class":82},"          ← 宏任务\n",[10,1974,1975],{},"E在B之前，因为await恢复是微任务，setTimeout是宏任务，我们分析就可以知道，微任务队列里面有Promise.then、await恢复，宏任务队列里面有SetTimeout。因此顺序就是同步A同步D同步F微任务C微任务E宏任务B。",[1977,1978,1979],"blockquote",{},[10,1980,1981,24,1984],{},[73,1982,1983],{},"!tip",[21,1985,1986],{},"事件循环负责协调调用栈、微任务队列和宏任务队列。同步代码在调用栈中执行；调用栈清空后，先清空所有微任务；然后取一个宏任务执行；如此循环。",[14,1988,1990],{"id":1989},"js的核心运行机制","JS的核心运行机制",[10,1992,1993],{},"刚才讲了同步、异步方法的细节，现在来讲讲执行上下文，这个是理解JS运行原理的核心，await、事件循环、this、变量查找都建立在执行上下文。",[10,1995,1996],{},"执行上下文是代码执行的环境，记录了： 变量环境（var、函数声明）、词法环境（let、const、块级作用域）、this绑定（当前函数的this指向）、外部环境引用（作用域链，用于变量查找）、代码类型（全局、函数、eval）。 每一次函数调用，都会创建一个新的执行上下文。",[10,1998,1999],{},"我们知道，js有三种上下文，分别是全局上下文，这个是脚本加载的时候创建的，是整个脚本的顶层代码。然后是函数上下文，每次调用函数的时候创建。最后是Eval上下文，eval()调用的时候会创建，很少使用。",[10,2001,2002],{},"全局上下文只有一个，函数上下文每次调用都会调用新建。‘",[64,2004,2009],{"className":2005,"code":2007,"language":2008},[2006],"language-text","1. 创建阶段\n   ├── 创建变量环境（var、函数声明）\n   ├── 创建词法环境（let、const）\n   ├── 确定 this 绑定\n   └── 建立作用域链\n\n2. 执行阶段\n   ├── 逐行执行代码\n   ├── 变量赋值\n   └── 函数调用（创建新的执行上下文）\n\n3. 销毁阶段\n   └── 函数返回，上下文出栈\n","text",[26,2010,2007],{"__ignoreMap":69},[10,2012,2013],{},"我举例一段代码：",[64,2015,2018],{"className":2016,"code":2017,"language":2008},[2006],"function a() {\n  console.log('a')\n  b()\n}\n\nfunction b() {\n  console.log('b')\n  c()\n}\n\nfunction c() {\n  console.log('c')\n}\n\na()\n",[26,2019,2017],{"__ignoreMap":69},[10,2021,2022],{},"上下文栈的变化：",[64,2024,2027],{"className":2025,"code":2026,"language":2008},[2006],"1. 全局上下文入栈\n   [全局]\n\n2. 调用 a()，a 的上下文入栈\n   [全局, a]\n\n3. a 里调用 b()，b 的上下文入栈\n   [全局, a, b]\n\n4. b 里调用 c()，c 的上下文入栈\n   [全局, a, b, c]\n\n5. c 执行完，c 出栈\n   [全局, a, b]\n\n6. b 执行完，b 出栈\n   [全局, a]\n\n7. a 执行完，a 出栈\n   [全局]\n\n8. 全局执行完，全局出栈\n   []\n",[26,2028,2026],{"__ignoreMap":69},[10,2030,2031],{},"然后我们来聊聊执行上下文和作用域链的关系：",[64,2033,2035],{"className":66,"code":2034,"language":68,"meta":69,"style":69},"function outer() {\n  const a = 1\n\n  function inner() {\n    const b = 2\n    console.log(a + b)  \u002F\u002F 3\n  }\n\n  inner()\n}\n",[26,2036,2037,2046,2058,2062,2072,2085,2104,2109,2113,2120],{"__ignoreMap":69},[73,2038,2039,2041,2044],{"class":75,"line":76},[73,2040,356],{"class":89},[73,2042,2043],{"class":284}," outer",[73,2045,1530],{"class":82},[73,2047,2048,2050,2053,2055],{"class":75,"line":102},[73,2049,1550],{"class":89},[73,2051,2052],{"class":79}," a",[73,2054,90],{"class":89},[73,2056,2057],{"class":79}," 1\n",[73,2059,2060],{"class":75,"line":120},[73,2061,437],{"emptyLinePlaceholder":436},[73,2063,2064,2067,2070],{"class":75,"line":139},[73,2065,2066],{"class":89},"  function",[73,2068,2069],{"class":284}," inner",[73,2071,1530],{"class":82},[73,2073,2074,2077,2080,2082],{"class":75,"line":159},[73,2075,2076],{"class":89},"    const",[73,2078,2079],{"class":79}," b",[73,2081,90],{"class":89},[73,2083,2084],{"class":79}," 2\n",[73,2086,2087,2090,2092,2095,2098,2101],{"class":75,"line":178},[73,2088,2089],{"class":82},"    console.",[73,2091,758],{"class":284},[73,2093,2094],{"class":82},"(a ",[73,2096,2097],{"class":89},"+",[73,2099,2100],{"class":82}," b)  ",[73,2102,2103],{"class":291},"\u002F\u002F 3\n",[73,2105,2106],{"class":75,"line":204},[73,2107,2108],{"class":82},"  }\n",[73,2110,2111],{"class":75,"line":1198},[73,2112,437],{"emptyLinePlaceholder":436},[73,2114,2115,2118],{"class":75,"line":1203},[73,2116,2117],{"class":284},"  inner",[73,2119,741],{"class":82},[73,2121,2122],{"class":75,"line":1209},[73,2123,746],{"class":82},[10,2125,2126],{},"用全局的视角来看，outer函数里包裹一个innre函数，inner的执行上下文（变量环境有b: 2，词法环境有b: 2）里面应该是找不到a的，那么他就会沿着作用域向上寻找，它找到了outer上下文的词法环境（变量环境a:1，外部引用->全局上下文）。",[10,2128,2129],{},"作用域链就是执行上下文的外部引用链，变量查找会沿着这条链向上寻找。",[10,2131,2132],{},"再来深入一点点，刚才我们说了变量环境和词法环境，这两个都是决定变量存放地方和查找、可访问的概念。",[64,2134,2137],{"className":2135,"code":2136,"language":2008},[2006],"执行上下文\n├── 词法环境（Lexical Environment）\n│   ├── 环境记录（Environment Record）\n│   │   ├── 声明式环境记录（let、const、class、函数声明）\n│   │   └── 对象环境记录（with、global 的 var）\n│   └── 外部环境引用（outer）\n│\n├── 变量环境（Variable Environment）\n│   └── 环境记录（主要放 var、函数声明）\n│\n└── this 绑定\n",[26,2138,2136],{"__ignoreMap":69},[10,2140,2141],{},"词法环境由环境记录、外部环境引用组成，环境记录存放的是let const class 函数声明 catch参数组成。外部环境记录指向外部词法环境，形成了作用域链。全局词法环境的外部引用指向null。块级词法环境的外部引用指向全局词法环境。",[10,2143,2144],{},"var和函数声明进入的是变量环境，是因为var和let\u002Fconst的作用域规则不同，var的作用域是函数级，变量会提升，初始化为undefined，如果是全局的话，会挂载到window上，let\u002Fconst作用域是块级，可以提升但是不会初始化（TDZ，这个我们了解过），不会挂载到window。",[10,2146,2147],{},"变量查找顺序",[10,2149,2150,2151,2154],{},"当代码里访问一个变量 ",[26,2152,2153],{},"x","：",[64,2156,2159],{"className":2157,"code":2158,"language":2008},[2006],"1. 先查当前词法环境的环境记录\n2. 找不到 → 查当前变量环境的环境记录\n3. 找不到 → 沿词法环境的外部引用往上找\n4. 找不到 → 沿变量环境的外部引用往上找\n5. 到全局还找不到 → ReferenceError\n",[26,2160,2158],{"__ignoreMap":69},[10,2162,2163],{},"块级作用域实现",[64,2165,2167],{"className":66,"code":2166,"language":68,"meta":69,"style":69},"{\n  let a = 1\n  const b = 2\n}\n",[26,2168,2169,2174,2186,2196],{"__ignoreMap":69},[73,2170,2171],{"class":75,"line":76},[73,2172,2173],{"class":82},"{\n",[73,2175,2176,2179,2182,2184],{"class":75,"line":102},[73,2177,2178],{"class":89},"  let",[73,2180,2181],{"class":82}," a ",[73,2183,989],{"class":89},[73,2185,2057],{"class":79},[73,2187,2188,2190,2192,2194],{"class":75,"line":120},[73,2189,1550],{"class":89},[73,2191,2079],{"class":79},[73,2193,90],{"class":89},[73,2195,2084],{"class":79},[73,2197,2198],{"class":75,"line":139},[73,2199,746],{"class":82},[10,2201,2202],{},"每进入一个代码块{}，就会创建一个新的词法环境。",[64,2204,2207],{"className":2205,"code":2206,"language":2008},[2006],"外层词法环境\n  ├── 环境记录: {}\n  └── 外部引用: null\n\n内层词法环境（{} 内）\n  ├── 环境记录: { a: 1, b: 2 }\n  └── 外部引用: → 外层词法环境\n",[26,2208,2206],{"__ignoreMap":69},[10,2210,2211],{},"这个可以多记忆一点，因为块级作用域的本质就是进入块级的时候创建词法环境，离开的时候销毁。let也会创建一个块级词法环境，for循环是let面试经常被问到的，为什么let可以解决var闭包问题。",[64,2213,2215],{"className":66,"code":2214,"language":68,"meta":69,"style":69},"for (var i = 0; i \u003C 3; i++) {\n  setTimeout(() => console.log(i), 0)\n}\n\u002F\u002F 输出：3 3 3\n",[26,2216,2217,2251,2271,2275],{"__ignoreMap":69},[73,2218,2219,2222,2225,2227,2230,2232,2235,2238,2240,2243,2246,2249],{"class":75,"line":76},[73,2220,2221],{"class":89},"for",[73,2223,2224],{"class":82}," (",[73,2226,983],{"class":89},[73,2228,2229],{"class":82}," i ",[73,2231,989],{"class":89},[73,2233,2234],{"class":79}," 0",[73,2236,2237],{"class":82},"; i ",[73,2239,1089],{"class":89},[73,2241,2242],{"class":79}," 3",[73,2244,2245],{"class":82},"; i",[73,2247,2248],{"class":89},"++",[73,2250,696],{"class":82},[73,2252,2253,2256,2258,2260,2262,2264,2267,2269],{"class":75,"line":102},[73,2254,2255],{"class":284},"  setTimeout",[73,2257,1763],{"class":82},[73,2259,1766],{"class":89},[73,2261,1769],{"class":82},[73,2263,758],{"class":284},[73,2265,2266],{"class":82},"(i), ",[73,2268,193],{"class":79},[73,2270,1545],{"class":82},[73,2272,2273],{"class":75,"line":120},[73,2274,746],{"class":82},[73,2276,2277],{"class":75,"line":139},[73,2278,2279],{"class":291},"\u002F\u002F 输出：3 3 3\n",[10,2281,2282],{},"var i 是函数级作用域，只有一个i，从结构上来看，全局执行上下文下是变量环境，变量环境里有i: 3（循环结束）。三个setTimeout回调在循环结束后执行，此时i = 3，三个闭包引用的是同一个i。而let在for循环中，每次迭代会创建一个新的词法环境，并复制上一轮的变量值。",[1977,2284,2285],{},[10,2286,2287,24,2289],{},[73,2288,1983],{},[21,2290,2291,2294,2295,2297],{},[26,2292,2293],{},"let"," 的“每次声明创建新绑定”语义，既导致了“不能重复声明”，也导致了“",[26,2296,2221],{}," 循环每轮新环境”。两者是同一规则的两个表现，不是因果关系。",[10,2299,2300],{},"函数作用域的实现",[64,2302,2304],{"className":66,"code":2303,"language":68,"meta":69,"style":69},"function foo() {\n  var a = 1\n  function bar() {}\n}\n",[26,2305,2306,2314,2325,2335],{"__ignoreMap":69},[73,2307,2308,2310,2312],{"class":75,"line":76},[73,2309,356],{"class":89},[73,2311,1039],{"class":284},[73,2313,1530],{"class":82},[73,2315,2316,2319,2321,2323],{"class":75,"line":102},[73,2317,2318],{"class":89},"  var",[73,2320,2181],{"class":82},[73,2322,989],{"class":89},[73,2324,2057],{"class":79},[73,2326,2327,2329,2332],{"class":75,"line":120},[73,2328,2066],{"class":89},[73,2330,2331],{"class":284}," bar",[73,2333,2334],{"class":82},"() {}\n",[73,2336,2337],{"class":75,"line":139},[73,2338,746],{"class":82},[10,2340,2341],{},"函数在调用时候创建新的执行上下文，foo函数有词法环境、变量环境，这个都知道。然后this指向undefined。",[10,2343,2344],{},"闭包的实现",[64,2346,2348],{"className":66,"code":2347,"language":68,"meta":69,"style":69},"function outer() {\n  let a = 1\n\n  function inner() {\n    console.log(a)  \u002F\u002F 访问外层的 a\n  }\n\n  return inner\n}\n\nconst fn = outer()\nfn()  \u002F\u002F 1\n",[26,2349,2350,2358,2368,2372,2380,2392,2396,2400,2407,2411,2415,2428],{"__ignoreMap":69},[73,2351,2352,2354,2356],{"class":75,"line":76},[73,2353,356],{"class":89},[73,2355,2043],{"class":284},[73,2357,1530],{"class":82},[73,2359,2360,2362,2364,2366],{"class":75,"line":102},[73,2361,2178],{"class":89},[73,2363,2181],{"class":82},[73,2365,989],{"class":89},[73,2367,2057],{"class":79},[73,2369,2370],{"class":75,"line":120},[73,2371,437],{"emptyLinePlaceholder":436},[73,2373,2374,2376,2378],{"class":75,"line":139},[73,2375,2066],{"class":89},[73,2377,2069],{"class":284},[73,2379,1530],{"class":82},[73,2381,2382,2384,2386,2389],{"class":75,"line":159},[73,2383,2089],{"class":82},[73,2385,758],{"class":284},[73,2387,2388],{"class":82},"(a)  ",[73,2390,2391],{"class":291},"\u002F\u002F 访问外层的 a\n",[73,2393,2394],{"class":75,"line":178},[73,2395,2108],{"class":82},[73,2397,2398],{"class":75,"line":204},[73,2399,437],{"emptyLinePlaceholder":436},[73,2401,2402,2404],{"class":75,"line":1198},[73,2403,701],{"class":89},[73,2405,2406],{"class":82}," inner\n",[73,2408,2409],{"class":75,"line":1203},[73,2410,746],{"class":82},[73,2412,2413],{"class":75,"line":1209},[73,2414,437],{"emptyLinePlaceholder":436},[73,2416,2417,2419,2422,2424,2426],{"class":75,"line":1215},[73,2418,423],{"class":89},[73,2420,2421],{"class":79}," fn",[73,2423,90],{"class":89},[73,2425,2043],{"class":284},[73,2427,741],{"class":82},[73,2429,2430,2433,2436],{"class":75,"line":1221},[73,2431,2432],{"class":284},"fn",[73,2434,2435],{"class":82},"()  ",[73,2437,2438],{"class":291},"\u002F\u002F 1\n",[10,2440,2441],{},"inner返回后，它的执行上下文应该被销毁的，但是我们发现inner作用域引用了outer的词法环境，所以outer的词法环境不会被回收。闭包就相当于一个函数+他创建时候的词法环境链。",[10,2443,2444],{},"作用域和执行上下文的关系",[10,2446,2447],{},"这个可能在面试会被提及，作用域是静态的词法概念，执行上下文是运行时概念。前者决定能够访问哪些变量，后者是执行时的环境。我们写代码的时候发现inner可以访问outer里的属性，这个就是写代码时候确认的，inner的词法作用域链上包含outer。",[14,2449,2450],{"id":2450},"this问题",[10,2452,2453,2454,2457,2458,2461],{},"this是",[21,2455,2456],{},"函数执行时的上下文对象","，它的值取决于",[21,2459,2460],{},"函数怎么被调用","，而不是怎么被定义（箭头函数除外）。",[10,2463,2464],{},"js里有五种绑定this的方法，分别是new绑定，this就会指向新创建的对象，比如说new Foo()，然后是显示绑定，call\u002Fapply\u002Fbind 指定对象，比如foo.call(this)，再就是隐式绑定，this会指向调用方法的对象，比如obj.foo()，再来是默认绑定，this会指向undefined(严格)\u002F(非严格)，最后是箭头函数，this会指向外层作用域this，()->this。",[10,2466,2467,2154,2470,2472],{},[21,2468,2469],{},"优先级高的规则赢",[26,2471,389],{}," > 显式 > 隐式 > 默认。\n箭头函数比较特殊，它不遵循前面4条规则，而是词法绑定，所以要单独列出来说。new呢，是最高优先级：",[64,2474,2476],{"className":66,"code":2475,"language":68,"meta":69,"style":69},"function Foo(name) {\n  this.name = name\n}\n\nconst obj = new Foo('张三')\nconsole.log(obj.name)  \u002F\u002F '张三'\n",[26,2477,2478,2492,2505,2509,2513,2533],{"__ignoreMap":69},[73,2479,2480,2482,2485,2487,2490],{"class":75,"line":76},[73,2481,356],{"class":89},[73,2483,2484],{"class":284}," Foo",[73,2486,496],{"class":82},[73,2488,2489],{"class":686},"name",[73,2491,696],{"class":82},[73,2493,2494,2497,2500,2502],{"class":75,"line":102},[73,2495,2496],{"class":79},"  this",[73,2498,2499],{"class":82},".name ",[73,2501,989],{"class":89},[73,2503,2504],{"class":82}," name\n",[73,2506,2507],{"class":75,"line":120},[73,2508,746],{"class":82},[73,2510,2511],{"class":75,"line":139},[73,2512,437],{"emptyLinePlaceholder":436},[73,2514,2515,2517,2520,2522,2524,2526,2528,2531],{"class":75,"line":159},[73,2516,423],{"class":89},[73,2518,2519],{"class":79}," obj",[73,2521,90],{"class":89},[73,2523,281],{"class":89},[73,2525,2484],{"class":284},[73,2527,496],{"class":82},[73,2529,2530],{"class":992},"'张三'",[73,2532,1545],{"class":82},[73,2534,2535,2537,2539,2542],{"class":75,"line":178},[73,2536,755],{"class":82},[73,2538,758],{"class":284},[73,2540,2541],{"class":82},"(obj.name)  ",[73,2543,2544],{"class":291},"\u002F\u002F '张三'\n",[10,2546,2547],{},"我们在typecsriptteam.native-preview中可以看看Function的定义：",[64,2549,2551],{"className":1157,"code":2550,"language":1159,"meta":69,"style":69},"interface FunctionConstructor {\n    \u002F**\n     * Creates a new function.\n     * @param args A list of arguments the function accepts.\n     *\u002F\n    new (...args: string[]): Function;\n    (...args: string[]): Function;\n    readonly prototype: Function;\n}\n\ndeclare var Function: FunctionConstructor;\n",[26,2552,2553,2562,2567,2572,2586,2591,2619,2640,2654,2658,2662],{"__ignoreMap":69},[73,2554,2555,2557,2560],{"class":75,"line":76},[73,2556,1363],{"class":89},[73,2558,2559],{"class":284}," FunctionConstructor",[73,2561,1369],{"class":82},[73,2563,2564],{"class":75,"line":102},[73,2565,2566],{"class":291},"    \u002F**\n",[73,2568,2569],{"class":75,"line":120},[73,2570,2571],{"class":291},"     * Creates a new function.\n",[73,2573,2574,2577,2580,2583],{"class":75,"line":139},[73,2575,2576],{"class":291},"     * ",[73,2578,2579],{"class":89},"@param",[73,2581,2582],{"class":82}," args",[73,2584,2585],{"class":291}," A list of arguments the function accepts.\n",[73,2587,2588],{"class":75,"line":159},[73,2589,2590],{"class":291},"     *\u002F\n",[73,2592,2593,2596,2598,2601,2604,2606,2609,2612,2614,2617],{"class":75,"line":178},[73,2594,2595],{"class":89},"    new",[73,2597,2224],{"class":82},[73,2599,2600],{"class":89},"...",[73,2602,2603],{"class":686},"args",[73,2605,690],{"class":89},[73,2607,2608],{"class":79}," string",[73,2610,2611],{"class":82},"[])",[73,2613,690],{"class":89},[73,2615,2616],{"class":284}," Function",[73,2618,1382],{"class":82},[73,2620,2621,2624,2626,2628,2630,2632,2634,2636,2638],{"class":75,"line":204},[73,2622,2623],{"class":82},"    (",[73,2625,2600],{"class":89},[73,2627,2603],{"class":686},[73,2629,690],{"class":89},[73,2631,2608],{"class":79},[73,2633,2611],{"class":82},[73,2635,690],{"class":89},[73,2637,2616],{"class":284},[73,2639,1382],{"class":82},[73,2641,2642,2645,2648,2650,2652],{"class":75,"line":1198},[73,2643,2644],{"class":89},"    readonly",[73,2646,2647],{"class":284}," prototype",[73,2649,690],{"class":89},[73,2651,2616],{"class":284},[73,2653,1382],{"class":82},[73,2655,2656],{"class":75,"line":1203},[73,2657,746],{"class":82},[73,2659,2660],{"class":75,"line":1209},[73,2661,437],{"emptyLinePlaceholder":436},[73,2663,2664,2667,2670,2672,2674,2676],{"class":75,"line":1215},[73,2665,2666],{"class":89},"declare",[73,2668,2669],{"class":89}," var",[73,2671,2616],{"class":82},[73,2673,690],{"class":89},[73,2675,2559],{"class":284},[73,2677,1382],{"class":82},[10,2679,2680],{},"new Function()和 Function()效果一样，都返回新函数，这个是Function的特殊之处，Function既是构造函数也是普通函数。readonly prototype: Function 表示Function.prototype是不可重新赋值的，表示Function.prototype是不可重新赋值。",[14,2682,2683],{"id":2683},"arguments",[10,2685,2686,2687,2690],{},"arguments是普通函数内部自动可用的一个",[21,2688,2689],{},"类数组对象","，包含了调用该函数时候传入的所有实参，他不是数组，但是长得像数组，可以按索引访问，也有length属性。",[64,2692,2695],{"className":2693,"code":2694,"language":2008},[2006],"function foo(a, b) {\n    console.log(arguments);        \u002F\u002F [1, 2, 3]（类数组）\n    console.log(arguments.length); \u002F\u002F 3\n    console.log(arguments[0]);     \u002F\u002F 1\n    console.log(arguments[1]);     \u002F\u002F 2\n    console.log(arguments[2]);     \u002F\u002F 3\n}\n\nfoo(1, 2, 3);\n",[26,2696,2694],{"__ignoreMap":69},[10,2698,2699],{},"而 fn: Function ， fn.length访问的就是这个方法至少需要多少个参数了，并且箭头函数也是有的，你可以访问得到。",[14,2701,2702],{"id":2702},"call实现",[64,2704,2706],{"className":1157,"code":2705,"language":1159,"meta":69,"style":69},"export {}\n\ndeclare global {\n  interface Function {\n    customBind(thisArg: any, ...args: any[]): (...innerArgs: any[]) => any\n  }\n}\n\nFunction.prototype.customBind = function (thisArg: any, ...args: any[]) {\n  const originalFn = this\n\n  if (typeof originalFn !== 'function') {\n    throw new TypeError('Function.prototype.customBind is not a function')\n  }\n\n  function boundFn(...innerArgs: any[]) {\n    const totalArgs = args.concat(innerArgs)\n\n    \u002F\u002F new 调用：忽略 thisArg，执行 new originalFn\n    if (new.target) {\n      return new (originalFn as any)(...totalArgs)\n    }\n\n    \u002F\u002F 普通调用：绑定 thisArg\n    return originalFn.apply(thisArg, totalArgs)\n  }\n\n  \u002F\u002F 不设置 boundFn.prototype，保持和原生 bind 一致\n  return boundFn\n}\n\n\u002F\u002F 测试\nconst obj = {\n    name: \"John\",\n    sayHello: function() {\n        console.log(`Hello, ${this.name}`);\n    }\n}\nconst sayHello = obj.sayHello.customBind(obj);\nsayHello(); \u002F\u002F Hello, John\nconst sayHello2 = obj.sayHello.bind(obj);\nsayHello2(); \u002F\u002F Hello, John\n",[26,2707,2708,2715,2719,2726,2735,2783,2787,2791,2795,2834,2846,2850,2870,2887,2891,2895,2914,2932,2936,2941,2957,2980,2985,2990,2996,3011,3016,3021,3027,3035,3040,3045,3051,3062,3074,3087,3112,3117,3122,3140,3152,3169],{"__ignoreMap":69},[73,2709,2710,2712],{"class":75,"line":76},[73,2711,675],{"class":89},[73,2713,2714],{"class":82}," {}\n",[73,2716,2717],{"class":75,"line":102},[73,2718,437],{"emptyLinePlaceholder":436},[73,2720,2721,2723],{"class":75,"line":120},[73,2722,2666],{"class":89},[73,2724,2725],{"class":82}," global {\n",[73,2727,2728,2731,2733],{"class":75,"line":139},[73,2729,2730],{"class":89},"  interface",[73,2732,2616],{"class":284},[73,2734,1369],{"class":82},[73,2736,2737,2740,2742,2745,2747,2750,2752,2754,2756,2758,2760,2762,2764,2766,2768,2771,2773,2775,2778,2780],{"class":75,"line":159},[73,2738,2739],{"class":284},"    customBind",[73,2741,496],{"class":82},[73,2743,2744],{"class":686},"thisArg",[73,2746,690],{"class":89},[73,2748,2749],{"class":79}," any",[73,2751,726],{"class":82},[73,2753,2600],{"class":89},[73,2755,2603],{"class":686},[73,2757,690],{"class":89},[73,2759,2749],{"class":79},[73,2761,2611],{"class":82},[73,2763,690],{"class":89},[73,2765,2224],{"class":82},[73,2767,2600],{"class":89},[73,2769,2770],{"class":686},"innerArgs",[73,2772,690],{"class":89},[73,2774,2749],{"class":79},[73,2776,2777],{"class":82},"[]) ",[73,2779,1766],{"class":89},[73,2781,2782],{"class":79}," any\n",[73,2784,2785],{"class":75,"line":178},[73,2786,2108],{"class":82},[73,2788,2789],{"class":75,"line":204},[73,2790,746],{"class":82},[73,2792,2793],{"class":75,"line":1198},[73,2794,437],{"emptyLinePlaceholder":436},[73,2796,2797,2800,2802,2804,2806,2809,2811,2813,2815,2817,2819,2821,2823,2825,2827,2829,2831],{"class":75,"line":1203},[73,2798,2799],{"class":79},"Function",[73,2801,484],{"class":82},[73,2803,487],{"class":79},[73,2805,484],{"class":82},[73,2807,2808],{"class":284},"customBind",[73,2810,90],{"class":89},[73,2812,678],{"class":89},[73,2814,2224],{"class":82},[73,2816,2744],{"class":686},[73,2818,690],{"class":89},[73,2820,2749],{"class":79},[73,2822,726],{"class":82},[73,2824,2600],{"class":89},[73,2826,2603],{"class":686},[73,2828,690],{"class":89},[73,2830,2749],{"class":79},[73,2832,2833],{"class":82},"[]) {\n",[73,2835,2836,2838,2841,2843],{"class":75,"line":1209},[73,2837,1550],{"class":89},[73,2839,2840],{"class":79}," originalFn",[73,2842,90],{"class":89},[73,2844,2845],{"class":79}," this\n",[73,2847,2848],{"class":75,"line":1215},[73,2849,437],{"emptyLinePlaceholder":436},[73,2851,2852,2855,2857,2859,2862,2865,2868],{"class":75,"line":1221},[73,2853,2854],{"class":89},"  if",[73,2856,2224],{"class":82},[73,2858,278],{"class":89},[73,2860,2861],{"class":82}," originalFn ",[73,2863,2864],{"class":89},"!==",[73,2866,2867],{"class":992}," 'function'",[73,2869,696],{"class":82},[73,2871,2872,2875,2877,2880,2882,2885],{"class":75,"line":1227},[73,2873,2874],{"class":89},"    throw",[73,2876,281],{"class":89},[73,2878,2879],{"class":284}," TypeError",[73,2881,496],{"class":82},[73,2883,2884],{"class":992},"'Function.prototype.customBind is not a function'",[73,2886,1545],{"class":82},[73,2888,2889],{"class":75,"line":1233},[73,2890,2108],{"class":82},[73,2892,2893],{"class":75,"line":1899},[73,2894,437],{"emptyLinePlaceholder":436},[73,2896,2897,2899,2902,2904,2906,2908,2910,2912],{"class":75,"line":1913},[73,2898,2066],{"class":89},[73,2900,2901],{"class":284}," boundFn",[73,2903,496],{"class":82},[73,2905,2600],{"class":89},[73,2907,2770],{"class":686},[73,2909,690],{"class":89},[73,2911,2749],{"class":79},[73,2913,2833],{"class":82},[73,2915,2916,2918,2921,2923,2926,2929],{"class":75,"line":1918},[73,2917,2076],{"class":89},[73,2919,2920],{"class":79}," totalArgs",[73,2922,90],{"class":89},[73,2924,2925],{"class":82}," args.",[73,2927,2928],{"class":284},"concat",[73,2930,2931],{"class":82},"(innerArgs)\n",[73,2933,2934],{"class":75,"line":1927},[73,2935,437],{"emptyLinePlaceholder":436},[73,2937,2938],{"class":75,"line":1935},[73,2939,2940],{"class":291},"    \u002F\u002F new 调用：忽略 thisArg，执行 new originalFn\n",[73,2942,2943,2946,2948,2950,2952,2955],{"class":75,"line":1943},[73,2944,2945],{"class":89},"    if",[73,2947,2224],{"class":82},[73,2949,389],{"class":89},[73,2951,484],{"class":82},[73,2953,2954],{"class":79},"target",[73,2956,696],{"class":82},[73,2958,2959,2962,2964,2967,2970,2972,2975,2977],{"class":75,"line":1952},[73,2960,2961],{"class":89},"      return",[73,2963,281],{"class":89},[73,2965,2966],{"class":82}," (originalFn ",[73,2968,2969],{"class":89},"as",[73,2971,2749],{"class":79},[73,2973,2974],{"class":82},")(",[73,2976,2600],{"class":89},[73,2978,2979],{"class":82},"totalArgs)\n",[73,2981,2982],{"class":75,"line":1966},[73,2983,2984],{"class":82},"    }\n",[73,2986,2988],{"class":75,"line":2987},23,[73,2989,437],{"emptyLinePlaceholder":436},[73,2991,2993],{"class":75,"line":2992},24,[73,2994,2995],{"class":291},"    \u002F\u002F 普通调用：绑定 thisArg\n",[73,2997,2999,3002,3005,3008],{"class":75,"line":2998},25,[73,3000,3001],{"class":89},"    return",[73,3003,3004],{"class":82}," originalFn.",[73,3006,3007],{"class":284},"apply",[73,3009,3010],{"class":82},"(thisArg, totalArgs)\n",[73,3012,3014],{"class":75,"line":3013},26,[73,3015,2108],{"class":82},[73,3017,3019],{"class":75,"line":3018},27,[73,3020,437],{"emptyLinePlaceholder":436},[73,3022,3024],{"class":75,"line":3023},28,[73,3025,3026],{"class":291},"  \u002F\u002F 不设置 boundFn.prototype，保持和原生 bind 一致\n",[73,3028,3030,3032],{"class":75,"line":3029},29,[73,3031,701],{"class":89},[73,3033,3034],{"class":82}," boundFn\n",[73,3036,3038],{"class":75,"line":3037},30,[73,3039,746],{"class":82},[73,3041,3043],{"class":75,"line":3042},31,[73,3044,437],{"emptyLinePlaceholder":436},[73,3046,3048],{"class":75,"line":3047},32,[73,3049,3050],{"class":291},"\u002F\u002F 测试\n",[73,3052,3054,3056,3058,3060],{"class":75,"line":3053},33,[73,3055,423],{"class":89},[73,3057,2519],{"class":79},[73,3059,90],{"class":89},[73,3061,1369],{"class":82},[73,3063,3065,3068,3071],{"class":75,"line":3064},34,[73,3066,3067],{"class":82},"    name: ",[73,3069,3070],{"class":992},"\"John\"",[73,3072,3073],{"class":82},",\n",[73,3075,3077,3080,3083,3085],{"class":75,"line":3076},35,[73,3078,3079],{"class":284},"    sayHello",[73,3081,3082],{"class":82},": ",[73,3084,356],{"class":89},[73,3086,1530],{"class":82},[73,3088,3090,3093,3095,3097,3100,3102,3104,3106,3109],{"class":75,"line":3089},36,[73,3091,3092],{"class":82},"        console.",[73,3094,758],{"class":284},[73,3096,496],{"class":82},[73,3098,3099],{"class":992},"`Hello, ${",[73,3101,867],{"class":79},[73,3103,484],{"class":992},[73,3105,2489],{"class":82},[73,3107,3108],{"class":992},"}`",[73,3110,3111],{"class":82},");\n",[73,3113,3115],{"class":75,"line":3114},37,[73,3116,2984],{"class":82},[73,3118,3120],{"class":75,"line":3119},38,[73,3121,746],{"class":82},[73,3123,3125,3127,3130,3132,3135,3137],{"class":75,"line":3124},39,[73,3126,423],{"class":89},[73,3128,3129],{"class":79}," sayHello",[73,3131,90],{"class":89},[73,3133,3134],{"class":82}," obj.sayHello.",[73,3136,2808],{"class":284},[73,3138,3139],{"class":82},"(obj);\n",[73,3141,3143,3146,3149],{"class":75,"line":3142},40,[73,3144,3145],{"class":284},"sayHello",[73,3147,3148],{"class":82},"(); ",[73,3150,3151],{"class":291},"\u002F\u002F Hello, John\n",[73,3153,3155,3157,3160,3162,3164,3167],{"class":75,"line":3154},41,[73,3156,423],{"class":89},[73,3158,3159],{"class":79}," sayHello2",[73,3161,90],{"class":89},[73,3163,3134],{"class":82},[73,3165,3166],{"class":284},"bind",[73,3168,3139],{"class":82},[73,3170,3172,3175,3177],{"class":75,"line":3171},42,[73,3173,3174],{"class":284},"sayHello2",[73,3176,3148],{"class":82},[73,3178,3151],{"class":291},[10,3180,3181],{},"这里实现非常简单，唯一有些新的是new.target属性，这个是ES6引入的原属性，只能在函数内部使用，值取决于函数怎么被调用。",[10,3183,3184],{},"如果一个函数是new Foo()这样被调用的话，那么new.target代表Foo函数本身，如果是Foo()调用的话，那么new.target代表undefined，所以说这个是用来区分构造调用和普通调用。",[10,3186,3187],{},"如果调用方式是：",[64,3189,3191],{"className":66,"code":3190,"language":68,"meta":69,"style":69},"const BoundPerson = Person.customBind({name: 'ignored'})\nconst p = new BoundPerson('real')\n\n而不能写成：\nif (this instanceof boundFn) {\n  return new originalFn(...totalArgs)\n}\n",[26,3192,3193,3216,3236,3240,3245,3261,3275],{"__ignoreMap":69},[73,3194,3195,3197,3200,3202,3205,3207,3210,3213],{"class":75,"line":76},[73,3196,423],{"class":89},[73,3198,3199],{"class":79}," BoundPerson",[73,3201,90],{"class":89},[73,3203,3204],{"class":82}," Person.",[73,3206,2808],{"class":284},[73,3208,3209],{"class":82},"({name: ",[73,3211,3212],{"class":992},"'ignored'",[73,3214,3215],{"class":82},"})\n",[73,3217,3218,3220,3223,3225,3227,3229,3231,3234],{"class":75,"line":102},[73,3219,423],{"class":89},[73,3221,3222],{"class":79}," p",[73,3224,90],{"class":89},[73,3226,281],{"class":89},[73,3228,3199],{"class":284},[73,3230,496],{"class":82},[73,3232,3233],{"class":992},"'real'",[73,3235,1545],{"class":82},[73,3237,3238],{"class":75,"line":120},[73,3239,437],{"emptyLinePlaceholder":436},[73,3241,3242],{"class":75,"line":139},[73,3243,3244],{"class":82},"而不能写成：\n",[73,3246,3247,3250,3252,3254,3257,3259],{"class":75,"line":159},[73,3248,3249],{"class":89},"if",[73,3251,2224],{"class":82},[73,3253,867],{"class":79},[73,3255,3256],{"class":89}," instanceof",[73,3258,2901],{"class":284},[73,3260,696],{"class":82},[73,3262,3263,3265,3267,3269,3271,3273],{"class":75,"line":178},[73,3264,701],{"class":89},[73,3266,281],{"class":89},[73,3268,2840],{"class":284},[73,3270,496],{"class":82},[73,3272,2600],{"class":89},[73,3274,2979],{"class":82},[73,3276,3277],{"class":75,"line":204},[73,3278,746],{"class":82},[10,3280,3281],{},"这里的调用方式会让new.target为BoundPerson，这样thisArgs就会被忽略了。如果写成了下面那种样子，this在new调用的时候是新创建的对象，它的原型是boundFn.prototype，如果boundFn.prototype是undefined，instanceof就会报错。",[14,3283,493],{"id":493},[10,3285,3286],{},"call的作用是立即调用一个函数，并手动指定函数内部的this指向，参数是逐个传入的。",[64,3288,3290],{"className":66,"code":3289,"language":68,"meta":69,"style":69},"function greet(greeting, punctuation) {\n  console.log(`${greeting}, ${this.name}${punctuation}`)\n}\n\nconst user = { name: '张三' }\n\ngreet.call(user, 'Hello', '!')  \u002F\u002F 'Hello, 张三!'\n",[26,3291,3292,3311,3342,3346,3350,3367,3371],{"__ignoreMap":69},[73,3293,3294,3296,3299,3301,3304,3306,3309],{"class":75,"line":76},[73,3295,356],{"class":89},[73,3297,3298],{"class":284}," greet",[73,3300,496],{"class":82},[73,3302,3303],{"class":686},"greeting",[73,3305,726],{"class":82},[73,3307,3308],{"class":686},"punctuation",[73,3310,696],{"class":82},[73,3312,3313,3315,3317,3319,3322,3324,3327,3329,3331,3333,3336,3338,3340],{"class":75,"line":102},[73,3314,1535],{"class":82},[73,3316,758],{"class":284},[73,3318,496],{"class":82},[73,3320,3321],{"class":992},"`${",[73,3323,3303],{"class":82},[73,3325,3326],{"class":992},"}, ${",[73,3328,867],{"class":79},[73,3330,484],{"class":992},[73,3332,2489],{"class":82},[73,3334,3335],{"class":992},"}${",[73,3337,3308],{"class":82},[73,3339,3108],{"class":992},[73,3341,1545],{"class":82},[73,3343,3344],{"class":75,"line":120},[73,3345,746],{"class":82},[73,3347,3348],{"class":75,"line":139},[73,3349,437],{"emptyLinePlaceholder":436},[73,3351,3352,3354,3357,3359,3362,3364],{"class":75,"line":159},[73,3353,423],{"class":89},[73,3355,3356],{"class":79}," user",[73,3358,90],{"class":89},[73,3360,3361],{"class":82}," { name: ",[73,3363,2530],{"class":992},[73,3365,3366],{"class":82}," }\n",[73,3368,3369],{"class":75,"line":178},[73,3370,437],{"emptyLinePlaceholder":436},[73,3372,3373,3376,3378,3381,3384,3386,3389,3391],{"class":75,"line":204},[73,3374,3375],{"class":82},"greet.",[73,3377,493],{"class":284},[73,3379,3380],{"class":82},"(user, ",[73,3382,3383],{"class":992},"'Hello'",[73,3385,726],{"class":82},[73,3387,3388],{"class":992},"'!'",[73,3390,1492],{"class":82},[73,3392,3393],{"class":291},"\u002F\u002F 'Hello, 张三!'\n",[10,3395,3396],{},"我们自己的实现大致如下：",[64,3398,3400],{"className":1157,"code":3399,"language":1159,"meta":69,"style":69},"export {}\n\ndeclare global {\n    interface Function {\n        customCall: (thisArgs : any, ...args: any[]) => any\n    }\n}\n\nFunction.prototype.customCall = function(thisArgs, ...args) {\n    thisArgs = thisArgs ?? globalThis\n    if (typeof thisArgs !== 'object' && typeof thisArgs !== 'function') {\n        thisArgs = Object(thisArgs)\n    }\n    const tempKey = Symbol('temp')\n    thisArgs[tempKey] = this\n    try{\n        return thisArgs[tempKey](...args)\n    } finally {\n        delete thisArgs[tempKey]\n    }\n}\n",[26,3401,3402,3408,3412,3418,3427,3460,3464,3468,3472,3501,3517,3546,3558,3562,3581,3590,3597,3610,3620,3628,3632],{"__ignoreMap":69},[73,3403,3404,3406],{"class":75,"line":76},[73,3405,675],{"class":89},[73,3407,2714],{"class":82},[73,3409,3410],{"class":75,"line":102},[73,3411,437],{"emptyLinePlaceholder":436},[73,3413,3414,3416],{"class":75,"line":120},[73,3415,2666],{"class":89},[73,3417,2725],{"class":82},[73,3419,3420,3423,3425],{"class":75,"line":139},[73,3421,3422],{"class":89},"    interface",[73,3424,2616],{"class":284},[73,3426,1369],{"class":82},[73,3428,3429,3432,3434,3436,3439,3442,3444,3446,3448,3450,3452,3454,3456,3458],{"class":75,"line":159},[73,3430,3431],{"class":284},"        customCall",[73,3433,690],{"class":89},[73,3435,2224],{"class":82},[73,3437,3438],{"class":686},"thisArgs",[73,3440,3441],{"class":89}," :",[73,3443,2749],{"class":79},[73,3445,726],{"class":82},[73,3447,2600],{"class":89},[73,3449,2603],{"class":686},[73,3451,690],{"class":89},[73,3453,2749],{"class":79},[73,3455,2777],{"class":82},[73,3457,1766],{"class":89},[73,3459,2782],{"class":79},[73,3461,3462],{"class":75,"line":178},[73,3463,2984],{"class":82},[73,3465,3466],{"class":75,"line":204},[73,3467,746],{"class":82},[73,3469,3470],{"class":75,"line":1198},[73,3471,437],{"emptyLinePlaceholder":436},[73,3473,3474,3476,3478,3480,3482,3485,3487,3489,3491,3493,3495,3497,3499],{"class":75,"line":1203},[73,3475,2799],{"class":79},[73,3477,484],{"class":82},[73,3479,487],{"class":79},[73,3481,484],{"class":82},[73,3483,3484],{"class":284},"customCall",[73,3486,90],{"class":89},[73,3488,678],{"class":89},[73,3490,496],{"class":82},[73,3492,3438],{"class":686},[73,3494,726],{"class":82},[73,3496,2600],{"class":89},[73,3498,2603],{"class":686},[73,3500,696],{"class":82},[73,3502,3503,3506,3508,3511,3514],{"class":75,"line":1209},[73,3504,3505],{"class":82},"    thisArgs ",[73,3507,989],{"class":89},[73,3509,3510],{"class":82}," thisArgs ",[73,3512,3513],{"class":89},"??",[73,3515,3516],{"class":82}," globalThis\n",[73,3518,3519,3521,3523,3525,3527,3529,3532,3535,3538,3540,3542,3544],{"class":75,"line":1215},[73,3520,2945],{"class":89},[73,3522,2224],{"class":82},[73,3524,278],{"class":89},[73,3526,3510],{"class":82},[73,3528,2864],{"class":89},[73,3530,3531],{"class":992}," 'object'",[73,3533,3534],{"class":89}," &&",[73,3536,3537],{"class":89}," typeof",[73,3539,3510],{"class":82},[73,3541,2864],{"class":89},[73,3543,2867],{"class":992},[73,3545,696],{"class":82},[73,3547,3548,3551,3553,3555],{"class":75,"line":1221},[73,3549,3550],{"class":82},"        thisArgs ",[73,3552,989],{"class":89},[73,3554,704],{"class":284},[73,3556,3557],{"class":82},"(thisArgs)\n",[73,3559,3560],{"class":75,"line":1227},[73,3561,2984],{"class":82},[73,3563,3564,3566,3569,3571,3574,3576,3579],{"class":75,"line":1233},[73,3565,2076],{"class":89},[73,3567,3568],{"class":79}," tempKey",[73,3570,90],{"class":89},[73,3572,3573],{"class":284}," Symbol",[73,3575,496],{"class":82},[73,3577,3578],{"class":992},"'temp'",[73,3580,1545],{"class":82},[73,3582,3583,3586,3588],{"class":75,"line":1899},[73,3584,3585],{"class":82},"    thisArgs[tempKey] ",[73,3587,989],{"class":89},[73,3589,2845],{"class":79},[73,3591,3592,3595],{"class":75,"line":1913},[73,3593,3594],{"class":89},"    try",[73,3596,2173],{"class":82},[73,3598,3599,3602,3605,3607],{"class":75,"line":1918},[73,3600,3601],{"class":89},"        return",[73,3603,3604],{"class":82}," thisArgs[tempKey](",[73,3606,2600],{"class":89},[73,3608,3609],{"class":82},"args)\n",[73,3611,3612,3615,3618],{"class":75,"line":1927},[73,3613,3614],{"class":82},"    } ",[73,3616,3617],{"class":89},"finally",[73,3619,1369],{"class":82},[73,3621,3622,3625],{"class":75,"line":1935},[73,3623,3624],{"class":89},"        delete",[73,3626,3627],{"class":82}," thisArgs[tempKey]\n",[73,3629,3630],{"class":75,"line":1943},[73,3631,2984],{"class":82},[73,3633,3634],{"class":75,"line":1952},[73,3635,746],{"class":82},[10,3637,3638,3639,3642],{},"apply和call有一点细致差别，仅仅是传递的非...args而是没展开的数组，直接传入 ",[26,3640,3641],{},"[...args]","即可。",[14,3644,3645],{"id":3645},"new的实现",[10,3647,3648,3649,3651,3652,3655],{},"现 ",[26,3650,389],{}," 是理解 JS 原型链和构造函数机制的经典练习，一个new分为经典的四步，首先是创建一个新对象obj，然后把obj的原型指向Foo.prototype (obj.",[21,3653,3654],{},"proto"," === Foo.prototype)，紧接以obj为this，执行Foo，传入参数，判断Foo的返回值，如果返回值是对象或者函数，那么就用这个返回值，如果不是，就返回原始值\u002F无返回值，用之前创建的obj。",[64,3657,3659],{"className":1157,"code":3658,"language":1159,"meta":69,"style":69},"export function mynew(Constructor: Function, ...args: any[]) {\n    const obj = Object.create(Constructor.prototype)\n    const result = Constructor.apply(obj, args) \u002F\u002F constructor.\n    if (result !== null && (typeof result === 'object' || typeof result === 'function')) return result\n    return obj\n}\n",[26,3660,3661,3691,3715,3735,3780,3787],{"__ignoreMap":69},[73,3662,3663,3665,3667,3670,3672,3675,3677,3679,3681,3683,3685,3687,3689],{"class":75,"line":76},[73,3664,675],{"class":89},[73,3666,678],{"class":89},[73,3668,3669],{"class":284}," mynew",[73,3671,496],{"class":82},[73,3673,3674],{"class":284},"Constructor",[73,3676,690],{"class":89},[73,3678,2616],{"class":284},[73,3680,726],{"class":82},[73,3682,2600],{"class":89},[73,3684,2603],{"class":686},[73,3686,690],{"class":89},[73,3688,2749],{"class":79},[73,3690,2833],{"class":82},[73,3692,3693,3695,3697,3699,3702,3705,3707,3709,3711,3713],{"class":75,"line":102},[73,3694,2076],{"class":89},[73,3696,2519],{"class":79},[73,3698,90],{"class":89},[73,3700,3701],{"class":82}," Object.",[73,3703,3704],{"class":284},"create",[73,3706,496],{"class":82},[73,3708,3674],{"class":79},[73,3710,484],{"class":82},[73,3712,487],{"class":79},[73,3714,1545],{"class":82},[73,3716,3717,3719,3722,3724,3727,3729,3732],{"class":75,"line":120},[73,3718,2076],{"class":89},[73,3720,3721],{"class":79}," result",[73,3723,90],{"class":89},[73,3725,3726],{"class":82}," Constructor.",[73,3728,3007],{"class":284},[73,3730,3731],{"class":82},"(obj, args) ",[73,3733,3734],{"class":291},"\u002F\u002F constructor.\n",[73,3736,3737,3739,3742,3744,3746,3748,3750,3752,3755,3758,3760,3763,3765,3767,3769,3771,3774,3777],{"class":75,"line":139},[73,3738,2945],{"class":89},[73,3740,3741],{"class":82}," (result ",[73,3743,2864],{"class":89},[73,3745,344],{"class":79},[73,3747,3534],{"class":89},[73,3749,2224],{"class":82},[73,3751,278],{"class":89},[73,3753,3754],{"class":82}," result ",[73,3756,3757],{"class":89},"===",[73,3759,3531],{"class":992},[73,3761,3762],{"class":89}," ||",[73,3764,3537],{"class":89},[73,3766,3754],{"class":82},[73,3768,3757],{"class":89},[73,3770,2867],{"class":992},[73,3772,3773],{"class":82},")) ",[73,3775,3776],{"class":89},"return",[73,3778,3779],{"class":82}," result\n",[73,3781,3782,3784],{"class":75,"line":159},[73,3783,3001],{"class":89},[73,3785,3786],{"class":82}," obj\n",[73,3788,3789],{"class":75,"line":178},[73,3790,746],{"class":82},[10,3792,3793,3794,3796,3797,3799,3800,3803,3804,3806],{},"前面我们已知，Function是一个特殊的东西，它自己是自己的构造函数，Function.",[21,3795,3654],{}," === Function.prototype，而Function.prototype.",[21,3798,3654],{}," === Object.prototype。一般对象的 ",[26,3801,3802],{},"__proto__"," 指向\"创建它的构造函数的 ",[26,3805,487],{},"\"，我们都知道prototype一般是obj，但是Function.prototype 类型是function，这是唯一的例外。",[10,3808,3809,3812,3813,3816,3817],{},[26,3810,3811],{},"Function.prototype.__proto__"," 指向 ",[26,3814,3815],{},"Object.prototype","也只是刚好说明了函数也是对象，所以原型链指向最终的Object.prototype。",[21,3818,3819,3820,3822,3823,3826,3827,3829,3830,3833,3834,3836,3837,232],{},"默认情况下，用 ",[26,3821,356],{}," 声明的函数，它的 ",[26,3824,3825],{},"constructor"," 都是 ",[26,3828,2799],{},"，它的 ",[26,3831,3832],{},"[[Prototype]]","（即 ",[26,3835,3802],{},"）都指向 ",[26,3838,3839],{},"Function.prototype",[14,3841,3842],{"id":3842},"promise",[10,3844,3845,3846,3851],{},"ECMA-262标准在Promise instance一节中，明确规定了Promise实例必须包含的核心内部槽，其中包括PromiseState： 一个字符串值，取值明确限定为pending，fulfilled、rejected三种状态，这个正式状态机的状态集合。然后是PromiseResult，用于存储promise完成的值，仅当PromiseState不为pending的时候才有意义。然后是一个PromiseFulfillReactions列表，存储当promise从pending转移到fulfilled的时候需要处理的记录，也就是注册的then回调。",[21,3847,3848],{},[26,3849,3850],{},"PromiseRejectReactions"," 是一个列表，用于存储当Promise从pending转移到reject的时候需要处理的记录。",[10,3853,3854],{},"标准的抽象操作定义了状态如果迁移，fulfillPromise可以讲一个状态为pending的promise转变为fulfilled，并设置PromiseResult，同时触发PromiseFulfillReactions中的任务。RejectPromise讲一个状态为pending的Promise转变为rejected。",[10,3856,3857,3858,3861,3862,645,3865,3861,3867,3870],{},"这些定义构成了一个严格的单向状态机：",[26,3859,3860],{},"pending"," → ",[26,3863,3864],{},"fulfilled",[26,3866,3860],{},[26,3868,3869],{},"rejected","，且状态一旦改变便不可逆。",[10,3872,3873],{},"机制是十分简单的，只是说签名稍微复杂一点，特别是then方法等的签名，这里我先写出来：",[64,3875,3877],{"className":1157,"code":3876,"language":1159,"meta":69,"style":69},"    then\u003CTResult1 = T, TResult2 = never>(\n        onFulfilled?: ((value: T) => TResult1 | CustomPromise\u003CTResult1>) | null,\n        onRejected?: ((reason: any) => TResult2 | CustomPromise\u003CTResult2>) | null\n    ): CustomPromise\u003CTResult1 | TResult2>;\n",[26,3878,3879,3908,3954,3995],{"__ignoreMap":69},[73,3880,3881,3884,3886,3889,3891,3894,3897,3899,3902,3905],{"class":75,"line":76},[73,3882,3883],{"class":82},"    then",[73,3885,1089],{"class":89},[73,3887,3888],{"class":82},"TResult1 ",[73,3890,989],{"class":89},[73,3892,3893],{"class":79}," T",[73,3895,3896],{"class":82},", TResult2 ",[73,3898,989],{"class":89},[73,3900,3901],{"class":82}," never",[73,3903,3904],{"class":89},">",[73,3906,3907],{"class":82},"(\n",[73,3909,3910,3913,3916,3919,3921,3923,3925,3928,3930,3933,3936,3939,3941,3944,3946,3948,3950,3952],{"class":75,"line":102},[73,3911,3912],{"class":82},"        onFulfilled",[73,3914,3915],{"class":89},"?:",[73,3917,3918],{"class":82}," ((",[73,3920,687],{"class":686},[73,3922,690],{"class":89},[73,3924,3893],{"class":284},[73,3926,3927],{"class":82},") ",[73,3929,1766],{"class":89},[73,3931,3932],{"class":82}," TResult1 ",[73,3934,3935],{"class":89},"|",[73,3937,3938],{"class":82}," CustomPromise",[73,3940,1089],{"class":89},[73,3942,3943],{"class":82},"TResult1",[73,3945,3904],{"class":89},[73,3947,3927],{"class":82},[73,3949,3935],{"class":89},[73,3951,344],{"class":79},[73,3953,3073],{"class":82},[73,3955,3956,3959,3961,3963,3966,3968,3970,3972,3974,3977,3979,3981,3983,3986,3988,3990,3992],{"class":75,"line":120},[73,3957,3958],{"class":82},"        onRejected",[73,3960,3915],{"class":89},[73,3962,3918],{"class":82},[73,3964,3965],{"class":686},"reason",[73,3967,690],{"class":89},[73,3969,2749],{"class":79},[73,3971,3927],{"class":82},[73,3973,1766],{"class":89},[73,3975,3976],{"class":82}," TResult2 ",[73,3978,3935],{"class":89},[73,3980,3938],{"class":82},[73,3982,1089],{"class":89},[73,3984,3985],{"class":82},"TResult2",[73,3987,3904],{"class":89},[73,3989,3927],{"class":82},[73,3991,3935],{"class":89},[73,3993,3994],{"class":79}," null\n",[73,3996,3997,4000,4002,4004,4006,4009,4011],{"class":75,"line":139},[73,3998,3999],{"class":82},"    ): CustomPromise",[73,4001,1089],{"class":89},[73,4003,3888],{"class":82},[73,4005,3935],{"class":89},[73,4007,4008],{"class":82}," TResult2",[73,4010,3904],{"class":89},[73,4012,1382],{"class":82},[10,4014,4015,4016,1353],{},"可以看到，then方法是接受一个回调函数，可以在回调函数里注册onFulfilled和onRejected，然后返回的是我们自己的Promise类型，拆开 ",[26,4017,4018],{},"onFulfilled",[64,4020,4022],{"className":1157,"code":4021,"language":1159,"meta":69,"style":69},"((value: T) => TResult1 | CustomPromise\u003CTResult1>) | null | undefined\n",[26,4023,4024],{"__ignoreMap":69},[73,4025,4026,4029,4031,4033,4035,4037,4039,4041,4043,4045,4047,4049,4051,4053,4055,4057,4060],{"class":75,"line":76},[73,4027,4028],{"class":82},"((",[73,4030,687],{"class":686},[73,4032,690],{"class":89},[73,4034,3893],{"class":284},[73,4036,3927],{"class":82},[73,4038,1766],{"class":89},[73,4040,3932],{"class":82},[73,4042,3935],{"class":89},[73,4044,3938],{"class":82},[73,4046,1089],{"class":89},[73,4048,3943],{"class":82},[73,4050,3904],{"class":89},[73,4052,3927],{"class":82},[73,4054,3935],{"class":89},[73,4056,344],{"class":79},[73,4058,4059],{"class":89}," |",[73,4061,4062],{"class":79}," undefined\n",[10,4064,4065,4066,1670,4069,4072,4073,4075],{},"可能是一个函数，可能是null和undefined，类型上onFulfilled只可能是这些，但是T和Promise不在这个类型里面，它们出现在这个函数的",[21,4067,4068],{},"参数",[21,4070,4071],{},"返回值","里，不是 ",[26,4074,4018],{}," 本身。",[10,4077,4078],{},"这里需要复习常见类型在布尔运算里的真值表：",[780,4080,4081,4099],{},[783,4082,4083],{},[786,4084,4085,4088,4094],{},[789,4086,4087],{},"类型",[789,4089,4090,4093],{},[26,4091,4092],{},"if (x)"," 为真分支",[789,4095,4096,4098],{},[26,4097,4092],{}," 为假分支",[799,4100,4101,4117,4134,4148,4160],{},[786,4102,4103,4108,4113],{},[804,4104,4105],{},[26,4106,4107],{},"unknown",[804,4109,4110,4111],{},"不变，仍是 ",[26,4112,4107],{},[804,4114,4110,4115],{},[26,4116,4107],{},[786,4118,4119,4124,4130],{},[804,4120,4121],{},[26,4122,4123],{},"never",[804,4125,4126,4129],{},[21,4127,4128],{},"不进入","（分支不可达）",[804,4131,4132,4129],{},[21,4133,4128],{},[786,4135,4136,4140,4143],{},[804,4137,4138],{},[26,4139,606],{},[804,4141,4142],{},"排除了",[804,4144,4145,4146],{},"只剩 ",[26,4147,606],{},[786,4149,4150,4154,4156],{},[804,4151,4152],{},[26,4153,629],{},[804,4155,4142],{},[804,4157,4145,4158],{},[26,4159,629],{},[786,4161,4162,4167,4169],{},[804,4163,4164],{},[26,4165,4166],{},"null | undefined",[804,4168,4142],{},[804,4170,4171,4172],{},"剩 ",[26,4173,4166],{},[64,4175,4177],{"className":1157,"code":4176,"language":1159,"meta":69,"style":69},"type PromiseState = 'pending' | 'fulfilled' | 'rejected';\n\ninterface CustomPromise\u003CT> {\n    state: PromiseState;\n    result: T | undefined;\n    PromiseFulfillReactions: ((value: any) => void)[];\n    PromiseRejectReactions: ((reason: any) => void)[];\n\n    resolve(value: T): void;\n    reject(reason?: any): void;\n\n    then\u003CTResult1 = T, TResult2 = never>(\n        onFulfilled?: ((value: T) => TResult1 | CustomPromise\u003CTResult1>) | null,\n        onRejected?: ((reason: any) => TResult2 | CustomPromise\u003CTResult2>) | null\n    ): CustomPromise\u003CTResult1 | TResult2>;\n\n    catch\u003CTResult = never>(\n        onRejected?: ((reason: any) => TResult | CustomPromise\u003CTResult>) | null\n    ): CustomPromise\u003CT | TResult>;\n}\n\n\n\nclass MyPromise\u003CT> implements CustomPromise\u003CT> {\n    state: PromiseState = 'pending';\n    result: T | undefined = undefined;\n    PromiseFulfillReactions: ((value: any) => void)[] = [];\n    PromiseRejectReactions: ((reason: any) => void)[] = [];\n\n    constructor(\n        executor?: (\n            resolve: (value: T) => void,\n            reject: (reason?: any) => void\n        ) => void\n    ) {\n        if (typeof executor === 'function') {\n            try {\n                executor(\n                    (value) => this.resolve(value),\n                    (reason) => this.reject(reason)\n                );\n            } catch (e) {\n                this.reject(e);\n            }\n        }\n    }\n\n    resolve(value: T): void {\n        if (this.state !== 'pending') return;\n        if (value instanceof MyPromise) {\n            value.then(\n                (v) => this.resolve(v as T),\n                (r) => this.reject(r)\n            );\n            return;\n        }\n\n        this.state = 'fulfilled';\n        this.result = value;\n\n        const reactions = this.PromiseFulfillReactions;\n        this.PromiseFulfillReactions = [];\n        this.PromiseRejectReactions = [];\n        for (const reaction of reactions) {\n            queueMicrotask(() => reaction(value));\n        }\n    }\n\n    reject(reason?: any): void {\n        if (this.state !== 'pending') return;\n\n        this.state = 'rejected';\n        this.result = reason;\n\n        const reactions = this.PromiseRejectReactions;\n        this.PromiseFulfillReactions = [];\n        this.PromiseRejectReactions = [];\n        for (const reaction of reactions) {\n            queueMicrotask(() => reaction(reason));\n        }\n    }\n\n    then\u003CTResult1 = T, TResult2 = never>(\n        onFulfilled?: ((value: T) => TResult1 | CustomPromise\u003CTResult1>) | null,\n        onRejected?: ((reason: any) => TResult2 | CustomPromise\u003CTResult2>) | null\n    ): CustomPromise\u003CTResult1 | TResult2> {\n        return new MyPromise\u003CTResult1 | TResult2>((resolve, reject) => {\n            const handlerFulfilled = (value: T) => {\n                if (typeof onFulfilled !== 'function') {\n                    resolve(value as unknown as TResult1);\n                    return;\n                }\n                try {\n                    const r = onFulfilled(value);\n                    if (r instanceof MyPromise) {\n                        r.then(\n                            (v) => resolve(v as TResult1),\n                            (e) => reject(e)\n                        );\n                    } else {\n                        resolve(r as TResult1);\n                    }\n                } catch (e) {\n                    reject(e);\n                }\n            };\n\n            const handlerRejected = (reason: any) => {\n                if (typeof onRejected !== 'function') {\n                    reject(reason);\n                    return;\n                }\n                try {\n                    const r = onRejected(reason);\n                    if (r instanceof MyPromise) {\n                        r.then(\n                            (v) => resolve(v as TResult1),\n                            (e) => reject(e)\n                        );\n                    } else {\n                        resolve(r as unknown as TResult1);\n                    }\n                } catch (e) {\n                    reject(e);\n                }\n            };\n\n            if (this.state === 'pending') {\n                this.PromiseFulfillReactions.push(handlerFulfilled);\n                this.PromiseRejectReactions.push(handlerRejected);\n            } else if (this.state === 'fulfilled') {\n                queueMicrotask(() => handlerFulfilled(this.result as T));\n            } else {\n                queueMicrotask(() => handlerRejected(this.result));\n            }\n        });\n    }\n\n    catch\u003CTResult = never>(\n        onRejected?: ((reason: any) => TResult | CustomPromise\u003CTResult>) | null\n    ): CustomPromise\u003CT | TResult> {\n        return this.then(null, onRejected);\n    }\n\n    static resolve\u003CT>(value: T): MyPromise\u003CT> {\n        return new MyPromise\u003CT>((resolve) => resolve(value));\n    }\n\n    static reject\u003CT = never>(reason?: any): MyPromise\u003CT> {\n        return new MyPromise\u003CT>((_, reject) => reject(reason));\n    }\n}\n\nMyPromise.resolve(10).then(\n    (v) => console.log('fulfilled', v),   \u002F\u002F fulfilled 10\n    (r) => console.log('rejected', r)\n);\n",[26,4178,4179,4204,4208,4222,4233,4249,4274,4297,4301,4323,4344,4348,4371,4409,4443,4463,4467,4483,4518,4536,4540,4544,4548,4552,4578,4592,4610,4638,4664,4668,4675,4685,4708,4730,4739,4744,4762,4769,4776,4797,4817,4822,4833,4846,4852,4858,4863,4868,4889,4911,4925,4935,4964,4985,4991,4999,5004,5009,5023,5036,5041,5057,5069,5081,5100,5115,5120,5125,5130,5151,5172,5177,5190,5202,5207,5221,5232,5243,5258,5272,5277,5282,5287,5310,5347,5382,5401,5433,5458,5477,5497,5505,5511,5519,5536,5551,5561,5584,5602,5608,5619,5634,5640,5650,5658,5663,5669,5674,5698,5716,5724,5731,5736,5743,5757,5770,5779,5800,5815,5820,5829,5846,5851,5860,5867,5872,5877,5882,5900,5914,5927,5949,5974,5983,6001,6006,6012,6017,6022,6037,6072,6091,6109,6114,6119,6152,6177,6182,6187,6222,6252,6257,6262,6267,6286,6312,6335],{"__ignoreMap":69},[73,4180,4181,4184,4187,4189,4192,4194,4197,4199,4202],{"class":75,"line":76},[73,4182,4183],{"class":89},"type",[73,4185,4186],{"class":284}," PromiseState",[73,4188,90],{"class":89},[73,4190,4191],{"class":992}," 'pending'",[73,4193,4059],{"class":89},[73,4195,4196],{"class":992}," 'fulfilled'",[73,4198,4059],{"class":89},[73,4200,4201],{"class":992}," 'rejected'",[73,4203,1382],{"class":82},[73,4205,4206],{"class":75,"line":102},[73,4207,437],{"emptyLinePlaceholder":436},[73,4209,4210,4212,4214,4216,4219],{"class":75,"line":120},[73,4211,1363],{"class":89},[73,4213,3938],{"class":284},[73,4215,1089],{"class":82},[73,4217,4218],{"class":284},"T",[73,4220,4221],{"class":82},"> {\n",[73,4223,4224,4227,4229,4231],{"class":75,"line":139},[73,4225,4226],{"class":686},"    state",[73,4228,690],{"class":89},[73,4230,4186],{"class":284},[73,4232,1382],{"class":82},[73,4234,4235,4238,4240,4242,4244,4247],{"class":75,"line":159},[73,4236,4237],{"class":686},"    result",[73,4239,690],{"class":89},[73,4241,3893],{"class":284},[73,4243,4059],{"class":89},[73,4245,4246],{"class":79}," undefined",[73,4248,1382],{"class":82},[73,4250,4251,4254,4256,4258,4260,4262,4264,4266,4268,4271],{"class":75,"line":178},[73,4252,4253],{"class":686},"    PromiseFulfillReactions",[73,4255,690],{"class":89},[73,4257,3918],{"class":82},[73,4259,687],{"class":686},[73,4261,690],{"class":89},[73,4263,2749],{"class":79},[73,4265,3927],{"class":82},[73,4267,1766],{"class":89},[73,4269,4270],{"class":79}," void",[73,4272,4273],{"class":82},")[];\n",[73,4275,4276,4279,4281,4283,4285,4287,4289,4291,4293,4295],{"class":75,"line":204},[73,4277,4278],{"class":686},"    PromiseRejectReactions",[73,4280,690],{"class":89},[73,4282,3918],{"class":82},[73,4284,3965],{"class":686},[73,4286,690],{"class":89},[73,4288,2749],{"class":79},[73,4290,3927],{"class":82},[73,4292,1766],{"class":89},[73,4294,4270],{"class":79},[73,4296,4273],{"class":82},[73,4298,4299],{"class":75,"line":1198},[73,4300,437],{"emptyLinePlaceholder":436},[73,4302,4303,4306,4308,4310,4312,4314,4317,4319,4321],{"class":75,"line":1203},[73,4304,4305],{"class":284},"    resolve",[73,4307,496],{"class":82},[73,4309,687],{"class":686},[73,4311,690],{"class":89},[73,4313,3893],{"class":284},[73,4315,4316],{"class":82},")",[73,4318,690],{"class":89},[73,4320,4270],{"class":79},[73,4322,1382],{"class":82},[73,4324,4325,4328,4330,4332,4334,4336,4338,4340,4342],{"class":75,"line":1209},[73,4326,4327],{"class":284},"    reject",[73,4329,496],{"class":82},[73,4331,3965],{"class":686},[73,4333,3915],{"class":89},[73,4335,2749],{"class":79},[73,4337,4316],{"class":82},[73,4339,690],{"class":89},[73,4341,4270],{"class":79},[73,4343,1382],{"class":82},[73,4345,4346],{"class":75,"line":1215},[73,4347,437],{"emptyLinePlaceholder":436},[73,4349,4350,4352,4354,4356,4358,4360,4362,4364,4366,4368],{"class":75,"line":1221},[73,4351,3883],{"class":284},[73,4353,1089],{"class":82},[73,4355,3943],{"class":284},[73,4357,90],{"class":89},[73,4359,3893],{"class":284},[73,4361,726],{"class":82},[73,4363,3985],{"class":284},[73,4365,90],{"class":89},[73,4367,3901],{"class":79},[73,4369,4370],{"class":82},">(\n",[73,4372,4373,4375,4377,4379,4381,4383,4385,4387,4389,4392,4394,4396,4398,4400,4403,4405,4407],{"class":75,"line":1227},[73,4374,3912],{"class":686},[73,4376,3915],{"class":89},[73,4378,3918],{"class":82},[73,4380,687],{"class":686},[73,4382,690],{"class":89},[73,4384,3893],{"class":284},[73,4386,3927],{"class":82},[73,4388,1766],{"class":89},[73,4390,4391],{"class":284}," TResult1",[73,4393,4059],{"class":89},[73,4395,3938],{"class":284},[73,4397,1089],{"class":82},[73,4399,3943],{"class":284},[73,4401,4402],{"class":82},">) ",[73,4404,3935],{"class":89},[73,4406,344],{"class":79},[73,4408,3073],{"class":82},[73,4410,4411,4413,4415,4417,4419,4421,4423,4425,4427,4429,4431,4433,4435,4437,4439,4441],{"class":75,"line":1233},[73,4412,3958],{"class":686},[73,4414,3915],{"class":89},[73,4416,3918],{"class":82},[73,4418,3965],{"class":686},[73,4420,690],{"class":89},[73,4422,2749],{"class":79},[73,4424,3927],{"class":82},[73,4426,1766],{"class":89},[73,4428,4008],{"class":284},[73,4430,4059],{"class":89},[73,4432,3938],{"class":284},[73,4434,1089],{"class":82},[73,4436,3985],{"class":284},[73,4438,4402],{"class":82},[73,4440,3935],{"class":89},[73,4442,3994],{"class":79},[73,4444,4445,4448,4450,4452,4454,4456,4458,4460],{"class":75,"line":1899},[73,4446,4447],{"class":82},"    )",[73,4449,690],{"class":89},[73,4451,3938],{"class":284},[73,4453,1089],{"class":82},[73,4455,3943],{"class":284},[73,4457,4059],{"class":89},[73,4459,4008],{"class":284},[73,4461,4462],{"class":82},">;\n",[73,4464,4465],{"class":75,"line":1913},[73,4466,437],{"emptyLinePlaceholder":436},[73,4468,4469,4472,4474,4477,4479,4481],{"class":75,"line":1918},[73,4470,4471],{"class":284},"    catch",[73,4473,1089],{"class":82},[73,4475,4476],{"class":284},"TResult",[73,4478,90],{"class":89},[73,4480,3901],{"class":79},[73,4482,4370],{"class":82},[73,4484,4485,4487,4489,4491,4493,4495,4497,4499,4501,4504,4506,4508,4510,4512,4514,4516],{"class":75,"line":1927},[73,4486,3958],{"class":686},[73,4488,3915],{"class":89},[73,4490,3918],{"class":82},[73,4492,3965],{"class":686},[73,4494,690],{"class":89},[73,4496,2749],{"class":79},[73,4498,3927],{"class":82},[73,4500,1766],{"class":89},[73,4502,4503],{"class":284}," TResult",[73,4505,4059],{"class":89},[73,4507,3938],{"class":284},[73,4509,1089],{"class":82},[73,4511,4476],{"class":284},[73,4513,4402],{"class":82},[73,4515,3935],{"class":89},[73,4517,3994],{"class":79},[73,4519,4520,4522,4524,4526,4528,4530,4532,4534],{"class":75,"line":1935},[73,4521,4447],{"class":82},[73,4523,690],{"class":89},[73,4525,3938],{"class":284},[73,4527,1089],{"class":82},[73,4529,4218],{"class":284},[73,4531,4059],{"class":89},[73,4533,4503],{"class":284},[73,4535,4462],{"class":82},[73,4537,4538],{"class":75,"line":1943},[73,4539,746],{"class":82},[73,4541,4542],{"class":75,"line":1952},[73,4543,437],{"emptyLinePlaceholder":436},[73,4545,4546],{"class":75,"line":1966},[73,4547,437],{"emptyLinePlaceholder":436},[73,4549,4550],{"class":75,"line":2987},[73,4551,437],{"emptyLinePlaceholder":436},[73,4553,4554,4557,4560,4562,4564,4567,4570,4572,4574,4576],{"class":75,"line":2992},[73,4555,4556],{"class":89},"class",[73,4558,4559],{"class":284}," MyPromise",[73,4561,1089],{"class":82},[73,4563,4218],{"class":284},[73,4565,4566],{"class":82},"> ",[73,4568,4569],{"class":89},"implements",[73,4571,3938],{"class":284},[73,4573,1089],{"class":82},[73,4575,4218],{"class":284},[73,4577,4221],{"class":82},[73,4579,4580,4582,4584,4586,4588,4590],{"class":75,"line":2998},[73,4581,4226],{"class":686},[73,4583,690],{"class":89},[73,4585,4186],{"class":284},[73,4587,90],{"class":89},[73,4589,4191],{"class":992},[73,4591,1382],{"class":82},[73,4593,4594,4596,4598,4600,4602,4604,4606,4608],{"class":75,"line":3013},[73,4595,4237],{"class":686},[73,4597,690],{"class":89},[73,4599,3893],{"class":284},[73,4601,4059],{"class":89},[73,4603,4246],{"class":79},[73,4605,90],{"class":89},[73,4607,4246],{"class":79},[73,4609,1382],{"class":82},[73,4611,4612,4614,4616,4618,4620,4622,4624,4626,4628,4630,4633,4635],{"class":75,"line":3018},[73,4613,4253],{"class":686},[73,4615,690],{"class":89},[73,4617,3918],{"class":82},[73,4619,687],{"class":686},[73,4621,690],{"class":89},[73,4623,2749],{"class":79},[73,4625,3927],{"class":82},[73,4627,1766],{"class":89},[73,4629,4270],{"class":79},[73,4631,4632],{"class":82},")[] ",[73,4634,989],{"class":89},[73,4636,4637],{"class":82}," [];\n",[73,4639,4640,4642,4644,4646,4648,4650,4652,4654,4656,4658,4660,4662],{"class":75,"line":3023},[73,4641,4278],{"class":686},[73,4643,690],{"class":89},[73,4645,3918],{"class":82},[73,4647,3965],{"class":686},[73,4649,690],{"class":89},[73,4651,2749],{"class":79},[73,4653,3927],{"class":82},[73,4655,1766],{"class":89},[73,4657,4270],{"class":79},[73,4659,4632],{"class":82},[73,4661,989],{"class":89},[73,4663,4637],{"class":82},[73,4665,4666],{"class":75,"line":3029},[73,4667,437],{"emptyLinePlaceholder":436},[73,4669,4670,4673],{"class":75,"line":3037},[73,4671,4672],{"class":89},"    constructor",[73,4674,3907],{"class":82},[73,4676,4677,4680,4682],{"class":75,"line":3042},[73,4678,4679],{"class":284},"        executor",[73,4681,3915],{"class":89},[73,4683,4684],{"class":82}," (\n",[73,4686,4687,4690,4692,4694,4696,4698,4700,4702,4704,4706],{"class":75,"line":3047},[73,4688,4689],{"class":284},"            resolve",[73,4691,690],{"class":89},[73,4693,2224],{"class":82},[73,4695,687],{"class":686},[73,4697,690],{"class":89},[73,4699,3893],{"class":284},[73,4701,3927],{"class":82},[73,4703,1766],{"class":89},[73,4705,4270],{"class":79},[73,4707,3073],{"class":82},[73,4709,4710,4713,4715,4717,4719,4721,4723,4725,4727],{"class":75,"line":3053},[73,4711,4712],{"class":284},"            reject",[73,4714,690],{"class":89},[73,4716,2224],{"class":82},[73,4718,3965],{"class":686},[73,4720,3915],{"class":89},[73,4722,2749],{"class":79},[73,4724,3927],{"class":82},[73,4726,1766],{"class":89},[73,4728,4729],{"class":79}," void\n",[73,4731,4732,4735,4737],{"class":75,"line":3064},[73,4733,4734],{"class":82},"        ) ",[73,4736,1766],{"class":89},[73,4738,4729],{"class":79},[73,4740,4741],{"class":75,"line":3076},[73,4742,4743],{"class":82},"    ) {\n",[73,4745,4746,4749,4751,4753,4756,4758,4760],{"class":75,"line":3089},[73,4747,4748],{"class":89},"        if",[73,4750,2224],{"class":82},[73,4752,278],{"class":89},[73,4754,4755],{"class":82}," executor ",[73,4757,3757],{"class":89},[73,4759,2867],{"class":992},[73,4761,696],{"class":82},[73,4763,4764,4767],{"class":75,"line":3114},[73,4765,4766],{"class":89},"            try",[73,4768,1369],{"class":82},[73,4770,4771,4774],{"class":75,"line":3119},[73,4772,4773],{"class":284},"                executor",[73,4775,3907],{"class":82},[73,4777,4778,4781,4783,4785,4787,4790,4792,4794],{"class":75,"line":3124},[73,4779,4780],{"class":82},"                    (",[73,4782,687],{"class":686},[73,4784,3927],{"class":82},[73,4786,1766],{"class":89},[73,4788,4789],{"class":79}," this",[73,4791,484],{"class":82},[73,4793,1800],{"class":284},[73,4795,4796],{"class":82},"(value),\n",[73,4798,4799,4801,4803,4805,4807,4809,4811,4814],{"class":75,"line":3142},[73,4800,4780],{"class":82},[73,4802,3965],{"class":686},[73,4804,3927],{"class":82},[73,4806,1766],{"class":89},[73,4808,4789],{"class":79},[73,4810,484],{"class":82},[73,4812,4813],{"class":284},"reject",[73,4815,4816],{"class":82},"(reason)\n",[73,4818,4819],{"class":75,"line":3154},[73,4820,4821],{"class":82},"                );\n",[73,4823,4824,4827,4830],{"class":75,"line":3171},[73,4825,4826],{"class":82},"            } ",[73,4828,4829],{"class":89},"catch",[73,4831,4832],{"class":82}," (e) {\n",[73,4834,4836,4839,4841,4843],{"class":75,"line":4835},43,[73,4837,4838],{"class":79},"                this",[73,4840,484],{"class":82},[73,4842,4813],{"class":284},[73,4844,4845],{"class":82},"(e);\n",[73,4847,4849],{"class":75,"line":4848},44,[73,4850,4851],{"class":82},"            }\n",[73,4853,4855],{"class":75,"line":4854},45,[73,4856,4857],{"class":82},"        }\n",[73,4859,4861],{"class":75,"line":4860},46,[73,4862,2984],{"class":82},[73,4864,4866],{"class":75,"line":4865},47,[73,4867,437],{"emptyLinePlaceholder":436},[73,4869,4871,4873,4875,4877,4879,4881,4883,4885,4887],{"class":75,"line":4870},48,[73,4872,4305],{"class":284},[73,4874,496],{"class":82},[73,4876,687],{"class":686},[73,4878,690],{"class":89},[73,4880,3893],{"class":284},[73,4882,4316],{"class":82},[73,4884,690],{"class":89},[73,4886,4270],{"class":79},[73,4888,1369],{"class":82},[73,4890,4892,4894,4896,4898,4901,4903,4905,4907,4909],{"class":75,"line":4891},49,[73,4893,4748],{"class":89},[73,4895,2224],{"class":82},[73,4897,867],{"class":79},[73,4899,4900],{"class":82},".state ",[73,4902,2864],{"class":89},[73,4904,4191],{"class":992},[73,4906,3927],{"class":82},[73,4908,3776],{"class":89},[73,4910,1382],{"class":82},[73,4912,4914,4916,4919,4921,4923],{"class":75,"line":4913},50,[73,4915,4748],{"class":89},[73,4917,4918],{"class":82}," (value ",[73,4920,397],{"class":89},[73,4922,4559],{"class":284},[73,4924,696],{"class":82},[73,4926,4928,4931,4933],{"class":75,"line":4927},51,[73,4929,4930],{"class":82},"            value.",[73,4932,1806],{"class":284},[73,4934,3907],{"class":82},[73,4936,4938,4941,4944,4946,4948,4950,4952,4954,4957,4959,4961],{"class":75,"line":4937},52,[73,4939,4940],{"class":82},"                (",[73,4942,4943],{"class":686},"v",[73,4945,3927],{"class":82},[73,4947,1766],{"class":89},[73,4949,4789],{"class":79},[73,4951,484],{"class":82},[73,4953,1800],{"class":284},[73,4955,4956],{"class":82},"(v ",[73,4958,2969],{"class":89},[73,4960,3893],{"class":284},[73,4962,4963],{"class":82},"),\n",[73,4965,4967,4969,4972,4974,4976,4978,4980,4982],{"class":75,"line":4966},53,[73,4968,4940],{"class":82},[73,4970,4971],{"class":686},"r",[73,4973,3927],{"class":82},[73,4975,1766],{"class":89},[73,4977,4789],{"class":79},[73,4979,484],{"class":82},[73,4981,4813],{"class":284},[73,4983,4984],{"class":82},"(r)\n",[73,4986,4988],{"class":75,"line":4987},54,[73,4989,4990],{"class":82},"            );\n",[73,4992,4994,4997],{"class":75,"line":4993},55,[73,4995,4996],{"class":89},"            return",[73,4998,1382],{"class":82},[73,5000,5002],{"class":75,"line":5001},56,[73,5003,4857],{"class":82},[73,5005,5007],{"class":75,"line":5006},57,[73,5008,437],{"emptyLinePlaceholder":436},[73,5010,5012,5015,5017,5019,5021],{"class":75,"line":5011},58,[73,5013,5014],{"class":79},"        this",[73,5016,4900],{"class":82},[73,5018,989],{"class":89},[73,5020,4196],{"class":992},[73,5022,1382],{"class":82},[73,5024,5026,5028,5031,5033],{"class":75,"line":5025},59,[73,5027,5014],{"class":79},[73,5029,5030],{"class":82},".result ",[73,5032,989],{"class":89},[73,5034,5035],{"class":82}," value;\n",[73,5037,5039],{"class":75,"line":5038},60,[73,5040,437],{"emptyLinePlaceholder":436},[73,5042,5044,5047,5050,5052,5054],{"class":75,"line":5043},61,[73,5045,5046],{"class":89},"        const",[73,5048,5049],{"class":79}," reactions",[73,5051,90],{"class":89},[73,5053,4789],{"class":79},[73,5055,5056],{"class":82},".PromiseFulfillReactions;\n",[73,5058,5060,5062,5065,5067],{"class":75,"line":5059},62,[73,5061,5014],{"class":79},[73,5063,5064],{"class":82},".PromiseFulfillReactions ",[73,5066,989],{"class":89},[73,5068,4637],{"class":82},[73,5070,5072,5074,5077,5079],{"class":75,"line":5071},63,[73,5073,5014],{"class":79},[73,5075,5076],{"class":82},".PromiseRejectReactions ",[73,5078,989],{"class":89},[73,5080,4637],{"class":82},[73,5082,5084,5087,5089,5091,5094,5097],{"class":75,"line":5083},64,[73,5085,5086],{"class":89},"        for",[73,5088,2224],{"class":82},[73,5090,423],{"class":89},[73,5092,5093],{"class":79}," reaction",[73,5095,5096],{"class":89}," of",[73,5098,5099],{"class":82}," reactions) {\n",[73,5101,5103,5106,5108,5110,5112],{"class":75,"line":5102},65,[73,5104,5105],{"class":284},"            queueMicrotask",[73,5107,1763],{"class":82},[73,5109,1766],{"class":89},[73,5111,5093],{"class":284},[73,5113,5114],{"class":82},"(value));\n",[73,5116,5118],{"class":75,"line":5117},66,[73,5119,4857],{"class":82},[73,5121,5123],{"class":75,"line":5122},67,[73,5124,2984],{"class":82},[73,5126,5128],{"class":75,"line":5127},68,[73,5129,437],{"emptyLinePlaceholder":436},[73,5131,5133,5135,5137,5139,5141,5143,5145,5147,5149],{"class":75,"line":5132},69,[73,5134,4327],{"class":284},[73,5136,496],{"class":82},[73,5138,3965],{"class":686},[73,5140,3915],{"class":89},[73,5142,2749],{"class":79},[73,5144,4316],{"class":82},[73,5146,690],{"class":89},[73,5148,4270],{"class":79},[73,5150,1369],{"class":82},[73,5152,5154,5156,5158,5160,5162,5164,5166,5168,5170],{"class":75,"line":5153},70,[73,5155,4748],{"class":89},[73,5157,2224],{"class":82},[73,5159,867],{"class":79},[73,5161,4900],{"class":82},[73,5163,2864],{"class":89},[73,5165,4191],{"class":992},[73,5167,3927],{"class":82},[73,5169,3776],{"class":89},[73,5171,1382],{"class":82},[73,5173,5175],{"class":75,"line":5174},71,[73,5176,437],{"emptyLinePlaceholder":436},[73,5178,5180,5182,5184,5186,5188],{"class":75,"line":5179},72,[73,5181,5014],{"class":79},[73,5183,4900],{"class":82},[73,5185,989],{"class":89},[73,5187,4201],{"class":992},[73,5189,1382],{"class":82},[73,5191,5193,5195,5197,5199],{"class":75,"line":5192},73,[73,5194,5014],{"class":79},[73,5196,5030],{"class":82},[73,5198,989],{"class":89},[73,5200,5201],{"class":82}," reason;\n",[73,5203,5205],{"class":75,"line":5204},74,[73,5206,437],{"emptyLinePlaceholder":436},[73,5208,5210,5212,5214,5216,5218],{"class":75,"line":5209},75,[73,5211,5046],{"class":89},[73,5213,5049],{"class":79},[73,5215,90],{"class":89},[73,5217,4789],{"class":79},[73,5219,5220],{"class":82},".PromiseRejectReactions;\n",[73,5222,5224,5226,5228,5230],{"class":75,"line":5223},76,[73,5225,5014],{"class":79},[73,5227,5064],{"class":82},[73,5229,989],{"class":89},[73,5231,4637],{"class":82},[73,5233,5235,5237,5239,5241],{"class":75,"line":5234},77,[73,5236,5014],{"class":79},[73,5238,5076],{"class":82},[73,5240,989],{"class":89},[73,5242,4637],{"class":82},[73,5244,5246,5248,5250,5252,5254,5256],{"class":75,"line":5245},78,[73,5247,5086],{"class":89},[73,5249,2224],{"class":82},[73,5251,423],{"class":89},[73,5253,5093],{"class":79},[73,5255,5096],{"class":89},[73,5257,5099],{"class":82},[73,5259,5261,5263,5265,5267,5269],{"class":75,"line":5260},79,[73,5262,5105],{"class":284},[73,5264,1763],{"class":82},[73,5266,1766],{"class":89},[73,5268,5093],{"class":284},[73,5270,5271],{"class":82},"(reason));\n",[73,5273,5275],{"class":75,"line":5274},80,[73,5276,4857],{"class":82},[73,5278,5280],{"class":75,"line":5279},81,[73,5281,2984],{"class":82},[73,5283,5285],{"class":75,"line":5284},82,[73,5286,437],{"emptyLinePlaceholder":436},[73,5288,5290,5292,5294,5296,5298,5300,5302,5304,5306,5308],{"class":75,"line":5289},83,[73,5291,3883],{"class":284},[73,5293,1089],{"class":82},[73,5295,3943],{"class":284},[73,5297,90],{"class":89},[73,5299,3893],{"class":284},[73,5301,726],{"class":82},[73,5303,3985],{"class":284},[73,5305,90],{"class":89},[73,5307,3901],{"class":79},[73,5309,4370],{"class":82},[73,5311,5313,5315,5317,5319,5321,5323,5325,5327,5329,5331,5333,5335,5337,5339,5341,5343,5345],{"class":75,"line":5312},84,[73,5314,3912],{"class":686},[73,5316,3915],{"class":89},[73,5318,3918],{"class":82},[73,5320,687],{"class":686},[73,5322,690],{"class":89},[73,5324,3893],{"class":284},[73,5326,3927],{"class":82},[73,5328,1766],{"class":89},[73,5330,4391],{"class":284},[73,5332,4059],{"class":89},[73,5334,3938],{"class":284},[73,5336,1089],{"class":82},[73,5338,3943],{"class":284},[73,5340,4402],{"class":82},[73,5342,3935],{"class":89},[73,5344,344],{"class":79},[73,5346,3073],{"class":82},[73,5348,5350,5352,5354,5356,5358,5360,5362,5364,5366,5368,5370,5372,5374,5376,5378,5380],{"class":75,"line":5349},85,[73,5351,3958],{"class":686},[73,5353,3915],{"class":89},[73,5355,3918],{"class":82},[73,5357,3965],{"class":686},[73,5359,690],{"class":89},[73,5361,2749],{"class":79},[73,5363,3927],{"class":82},[73,5365,1766],{"class":89},[73,5367,4008],{"class":284},[73,5369,4059],{"class":89},[73,5371,3938],{"class":284},[73,5373,1089],{"class":82},[73,5375,3985],{"class":284},[73,5377,4402],{"class":82},[73,5379,3935],{"class":89},[73,5381,3994],{"class":79},[73,5383,5385,5387,5389,5391,5393,5395,5397,5399],{"class":75,"line":5384},86,[73,5386,4447],{"class":82},[73,5388,690],{"class":89},[73,5390,3938],{"class":284},[73,5392,1089],{"class":82},[73,5394,3943],{"class":284},[73,5396,4059],{"class":89},[73,5398,4008],{"class":284},[73,5400,4221],{"class":82},[73,5402,5404,5406,5408,5410,5412,5414,5416,5418,5421,5423,5425,5427,5429,5431],{"class":75,"line":5403},87,[73,5405,3601],{"class":89},[73,5407,281],{"class":89},[73,5409,4559],{"class":284},[73,5411,1089],{"class":82},[73,5413,3943],{"class":284},[73,5415,4059],{"class":89},[73,5417,4008],{"class":284},[73,5419,5420],{"class":82},">((",[73,5422,1800],{"class":686},[73,5424,726],{"class":82},[73,5426,4813],{"class":686},[73,5428,3927],{"class":82},[73,5430,1766],{"class":89},[73,5432,1369],{"class":82},[73,5434,5436,5439,5442,5444,5446,5448,5450,5452,5454,5456],{"class":75,"line":5435},88,[73,5437,5438],{"class":89},"            const",[73,5440,5441],{"class":284}," handlerFulfilled",[73,5443,90],{"class":89},[73,5445,2224],{"class":82},[73,5447,687],{"class":686},[73,5449,690],{"class":89},[73,5451,3893],{"class":284},[73,5453,3927],{"class":82},[73,5455,1766],{"class":89},[73,5457,1369],{"class":82},[73,5459,5461,5464,5466,5468,5471,5473,5475],{"class":75,"line":5460},89,[73,5462,5463],{"class":89},"                if",[73,5465,2224],{"class":82},[73,5467,278],{"class":89},[73,5469,5470],{"class":82}," onFulfilled ",[73,5472,2864],{"class":89},[73,5474,2867],{"class":992},[73,5476,696],{"class":82},[73,5478,5480,5483,5486,5488,5490,5493,5495],{"class":75,"line":5479},90,[73,5481,5482],{"class":284},"                    resolve",[73,5484,5485],{"class":82},"(value ",[73,5487,2969],{"class":89},[73,5489,693],{"class":79},[73,5491,5492],{"class":89}," as",[73,5494,4391],{"class":284},[73,5496,3111],{"class":82},[73,5498,5500,5503],{"class":75,"line":5499},91,[73,5501,5502],{"class":89},"                    return",[73,5504,1382],{"class":82},[73,5506,5508],{"class":75,"line":5507},92,[73,5509,5510],{"class":82},"                }\n",[73,5512,5514,5517],{"class":75,"line":5513},93,[73,5515,5516],{"class":89},"                try",[73,5518,1369],{"class":82},[73,5520,5522,5525,5528,5530,5533],{"class":75,"line":5521},94,[73,5523,5524],{"class":89},"                    const",[73,5526,5527],{"class":79}," r",[73,5529,90],{"class":89},[73,5531,5532],{"class":284}," onFulfilled",[73,5534,5535],{"class":82},"(value);\n",[73,5537,5539,5542,5545,5547,5549],{"class":75,"line":5538},95,[73,5540,5541],{"class":89},"                    if",[73,5543,5544],{"class":82}," (r ",[73,5546,397],{"class":89},[73,5548,4559],{"class":284},[73,5550,696],{"class":82},[73,5552,5554,5557,5559],{"class":75,"line":5553},96,[73,5555,5556],{"class":82},"                        r.",[73,5558,1806],{"class":284},[73,5560,3907],{"class":82},[73,5562,5564,5567,5569,5571,5573,5576,5578,5580,5582],{"class":75,"line":5563},97,[73,5565,5566],{"class":82},"                            (",[73,5568,4943],{"class":686},[73,5570,3927],{"class":82},[73,5572,1766],{"class":89},[73,5574,5575],{"class":284}," resolve",[73,5577,4956],{"class":82},[73,5579,2969],{"class":89},[73,5581,4391],{"class":284},[73,5583,4963],{"class":82},[73,5585,5587,5589,5592,5594,5596,5599],{"class":75,"line":5586},98,[73,5588,5566],{"class":82},[73,5590,5591],{"class":686},"e",[73,5593,3927],{"class":82},[73,5595,1766],{"class":89},[73,5597,5598],{"class":284}," reject",[73,5600,5601],{"class":82},"(e)\n",[73,5603,5605],{"class":75,"line":5604},99,[73,5606,5607],{"class":82},"                        );\n",[73,5609,5611,5614,5617],{"class":75,"line":5610},100,[73,5612,5613],{"class":82},"                    } ",[73,5615,5616],{"class":89},"else",[73,5618,1369],{"class":82},[73,5620,5622,5625,5628,5630,5632],{"class":75,"line":5621},101,[73,5623,5624],{"class":284},"                        resolve",[73,5626,5627],{"class":82},"(r ",[73,5629,2969],{"class":89},[73,5631,4391],{"class":284},[73,5633,3111],{"class":82},[73,5635,5637],{"class":75,"line":5636},102,[73,5638,5639],{"class":82},"                    }\n",[73,5641,5643,5646,5648],{"class":75,"line":5642},103,[73,5644,5645],{"class":82},"                } ",[73,5647,4829],{"class":89},[73,5649,4832],{"class":82},[73,5651,5653,5656],{"class":75,"line":5652},104,[73,5654,5655],{"class":284},"                    reject",[73,5657,4845],{"class":82},[73,5659,5661],{"class":75,"line":5660},105,[73,5662,5510],{"class":82},[73,5664,5666],{"class":75,"line":5665},106,[73,5667,5668],{"class":82},"            };\n",[73,5670,5672],{"class":75,"line":5671},107,[73,5673,437],{"emptyLinePlaceholder":436},[73,5675,5677,5679,5682,5684,5686,5688,5690,5692,5694,5696],{"class":75,"line":5676},108,[73,5678,5438],{"class":89},[73,5680,5681],{"class":284}," handlerRejected",[73,5683,90],{"class":89},[73,5685,2224],{"class":82},[73,5687,3965],{"class":686},[73,5689,690],{"class":89},[73,5691,2749],{"class":79},[73,5693,3927],{"class":82},[73,5695,1766],{"class":89},[73,5697,1369],{"class":82},[73,5699,5701,5703,5705,5707,5710,5712,5714],{"class":75,"line":5700},109,[73,5702,5463],{"class":89},[73,5704,2224],{"class":82},[73,5706,278],{"class":89},[73,5708,5709],{"class":82}," onRejected ",[73,5711,2864],{"class":89},[73,5713,2867],{"class":992},[73,5715,696],{"class":82},[73,5717,5719,5721],{"class":75,"line":5718},110,[73,5720,5655],{"class":284},[73,5722,5723],{"class":82},"(reason);\n",[73,5725,5727,5729],{"class":75,"line":5726},111,[73,5728,5502],{"class":89},[73,5730,1382],{"class":82},[73,5732,5734],{"class":75,"line":5733},112,[73,5735,5510],{"class":82},[73,5737,5739,5741],{"class":75,"line":5738},113,[73,5740,5516],{"class":89},[73,5742,1369],{"class":82},[73,5744,5746,5748,5750,5752,5755],{"class":75,"line":5745},114,[73,5747,5524],{"class":89},[73,5749,5527],{"class":79},[73,5751,90],{"class":89},[73,5753,5754],{"class":284}," onRejected",[73,5756,5723],{"class":82},[73,5758,5760,5762,5764,5766,5768],{"class":75,"line":5759},115,[73,5761,5541],{"class":89},[73,5763,5544],{"class":82},[73,5765,397],{"class":89},[73,5767,4559],{"class":284},[73,5769,696],{"class":82},[73,5771,5773,5775,5777],{"class":75,"line":5772},116,[73,5774,5556],{"class":82},[73,5776,1806],{"class":284},[73,5778,3907],{"class":82},[73,5780,5782,5784,5786,5788,5790,5792,5794,5796,5798],{"class":75,"line":5781},117,[73,5783,5566],{"class":82},[73,5785,4943],{"class":686},[73,5787,3927],{"class":82},[73,5789,1766],{"class":89},[73,5791,5575],{"class":284},[73,5793,4956],{"class":82},[73,5795,2969],{"class":89},[73,5797,4391],{"class":284},[73,5799,4963],{"class":82},[73,5801,5803,5805,5807,5809,5811,5813],{"class":75,"line":5802},118,[73,5804,5566],{"class":82},[73,5806,5591],{"class":686},[73,5808,3927],{"class":82},[73,5810,1766],{"class":89},[73,5812,5598],{"class":284},[73,5814,5601],{"class":82},[73,5816,5818],{"class":75,"line":5817},119,[73,5819,5607],{"class":82},[73,5821,5823,5825,5827],{"class":75,"line":5822},120,[73,5824,5613],{"class":82},[73,5826,5616],{"class":89},[73,5828,1369],{"class":82},[73,5830,5832,5834,5836,5838,5840,5842,5844],{"class":75,"line":5831},121,[73,5833,5624],{"class":284},[73,5835,5627],{"class":82},[73,5837,2969],{"class":89},[73,5839,693],{"class":79},[73,5841,5492],{"class":89},[73,5843,4391],{"class":284},[73,5845,3111],{"class":82},[73,5847,5849],{"class":75,"line":5848},122,[73,5850,5639],{"class":82},[73,5852,5854,5856,5858],{"class":75,"line":5853},123,[73,5855,5645],{"class":82},[73,5857,4829],{"class":89},[73,5859,4832],{"class":82},[73,5861,5863,5865],{"class":75,"line":5862},124,[73,5864,5655],{"class":284},[73,5866,4845],{"class":82},[73,5868,5870],{"class":75,"line":5869},125,[73,5871,5510],{"class":82},[73,5873,5875],{"class":75,"line":5874},126,[73,5876,5668],{"class":82},[73,5878,5880],{"class":75,"line":5879},127,[73,5881,437],{"emptyLinePlaceholder":436},[73,5883,5885,5888,5890,5892,5894,5896,5898],{"class":75,"line":5884},128,[73,5886,5887],{"class":89},"            if",[73,5889,2224],{"class":82},[73,5891,867],{"class":79},[73,5893,4900],{"class":82},[73,5895,3757],{"class":89},[73,5897,4191],{"class":992},[73,5899,696],{"class":82},[73,5901,5903,5905,5908,5911],{"class":75,"line":5902},129,[73,5904,4838],{"class":79},[73,5906,5907],{"class":82},".PromiseFulfillReactions.",[73,5909,5910],{"class":284},"push",[73,5912,5913],{"class":82},"(handlerFulfilled);\n",[73,5915,5917,5919,5922,5924],{"class":75,"line":5916},130,[73,5918,4838],{"class":79},[73,5920,5921],{"class":82},".PromiseRejectReactions.",[73,5923,5910],{"class":284},[73,5925,5926],{"class":82},"(handlerRejected);\n",[73,5928,5930,5932,5934,5937,5939,5941,5943,5945,5947],{"class":75,"line":5929},131,[73,5931,4826],{"class":82},[73,5933,5616],{"class":89},[73,5935,5936],{"class":89}," if",[73,5938,2224],{"class":82},[73,5940,867],{"class":79},[73,5942,4900],{"class":82},[73,5944,3757],{"class":89},[73,5946,4196],{"class":992},[73,5948,696],{"class":82},[73,5950,5952,5955,5957,5959,5961,5963,5965,5967,5969,5971],{"class":75,"line":5951},132,[73,5953,5954],{"class":284},"                queueMicrotask",[73,5956,1763],{"class":82},[73,5958,1766],{"class":89},[73,5960,5441],{"class":284},[73,5962,496],{"class":82},[73,5964,867],{"class":79},[73,5966,5030],{"class":82},[73,5968,2969],{"class":89},[73,5970,3893],{"class":284},[73,5972,5973],{"class":82},"));\n",[73,5975,5977,5979,5981],{"class":75,"line":5976},133,[73,5978,4826],{"class":82},[73,5980,5616],{"class":89},[73,5982,1369],{"class":82},[73,5984,5986,5988,5990,5992,5994,5996,5998],{"class":75,"line":5985},134,[73,5987,5954],{"class":284},[73,5989,1763],{"class":82},[73,5991,1766],{"class":89},[73,5993,5681],{"class":284},[73,5995,496],{"class":82},[73,5997,867],{"class":79},[73,5999,6000],{"class":82},".result));\n",[73,6002,6004],{"class":75,"line":6003},135,[73,6005,4851],{"class":82},[73,6007,6009],{"class":75,"line":6008},136,[73,6010,6011],{"class":82},"        });\n",[73,6013,6015],{"class":75,"line":6014},137,[73,6016,2984],{"class":82},[73,6018,6020],{"class":75,"line":6019},138,[73,6021,437],{"emptyLinePlaceholder":436},[73,6023,6025,6027,6029,6031,6033,6035],{"class":75,"line":6024},139,[73,6026,4471],{"class":284},[73,6028,1089],{"class":82},[73,6030,4476],{"class":284},[73,6032,90],{"class":89},[73,6034,3901],{"class":79},[73,6036,4370],{"class":82},[73,6038,6040,6042,6044,6046,6048,6050,6052,6054,6056,6058,6060,6062,6064,6066,6068,6070],{"class":75,"line":6039},140,[73,6041,3958],{"class":686},[73,6043,3915],{"class":89},[73,6045,3918],{"class":82},[73,6047,3965],{"class":686},[73,6049,690],{"class":89},[73,6051,2749],{"class":79},[73,6053,3927],{"class":82},[73,6055,1766],{"class":89},[73,6057,4503],{"class":284},[73,6059,4059],{"class":89},[73,6061,3938],{"class":284},[73,6063,1089],{"class":82},[73,6065,4476],{"class":284},[73,6067,4402],{"class":82},[73,6069,3935],{"class":89},[73,6071,3994],{"class":79},[73,6073,6075,6077,6079,6081,6083,6085,6087,6089],{"class":75,"line":6074},141,[73,6076,4447],{"class":82},[73,6078,690],{"class":89},[73,6080,3938],{"class":284},[73,6082,1089],{"class":82},[73,6084,4218],{"class":284},[73,6086,4059],{"class":89},[73,6088,4503],{"class":284},[73,6090,4221],{"class":82},[73,6092,6094,6096,6098,6100,6102,6104,6106],{"class":75,"line":6093},142,[73,6095,3601],{"class":89},[73,6097,4789],{"class":79},[73,6099,484],{"class":82},[73,6101,1806],{"class":284},[73,6103,496],{"class":82},[73,6105,606],{"class":79},[73,6107,6108],{"class":82},", onRejected);\n",[73,6110,6112],{"class":75,"line":6111},143,[73,6113,2984],{"class":82},[73,6115,6117],{"class":75,"line":6116},144,[73,6118,437],{"emptyLinePlaceholder":436},[73,6120,6122,6125,6127,6129,6131,6134,6136,6138,6140,6142,6144,6146,6148,6150],{"class":75,"line":6121},145,[73,6123,6124],{"class":89},"    static",[73,6126,5575],{"class":284},[73,6128,1089],{"class":82},[73,6130,4218],{"class":284},[73,6132,6133],{"class":82},">(",[73,6135,687],{"class":686},[73,6137,690],{"class":89},[73,6139,3893],{"class":284},[73,6141,4316],{"class":82},[73,6143,690],{"class":89},[73,6145,4559],{"class":284},[73,6147,1089],{"class":82},[73,6149,4218],{"class":284},[73,6151,4221],{"class":82},[73,6153,6155,6157,6159,6161,6163,6165,6167,6169,6171,6173,6175],{"class":75,"line":6154},146,[73,6156,3601],{"class":89},[73,6158,281],{"class":89},[73,6160,4559],{"class":284},[73,6162,1089],{"class":82},[73,6164,4218],{"class":284},[73,6166,5420],{"class":82},[73,6168,1800],{"class":686},[73,6170,3927],{"class":82},[73,6172,1766],{"class":89},[73,6174,5575],{"class":284},[73,6176,5114],{"class":82},[73,6178,6180],{"class":75,"line":6179},147,[73,6181,2984],{"class":82},[73,6183,6185],{"class":75,"line":6184},148,[73,6186,437],{"emptyLinePlaceholder":436},[73,6188,6190,6192,6194,6196,6198,6200,6202,6204,6206,6208,6210,6212,6214,6216,6218,6220],{"class":75,"line":6189},149,[73,6191,6124],{"class":89},[73,6193,5598],{"class":284},[73,6195,1089],{"class":82},[73,6197,4218],{"class":284},[73,6199,90],{"class":89},[73,6201,3901],{"class":79},[73,6203,6133],{"class":82},[73,6205,3965],{"class":686},[73,6207,3915],{"class":89},[73,6209,2749],{"class":79},[73,6211,4316],{"class":82},[73,6213,690],{"class":89},[73,6215,4559],{"class":284},[73,6217,1089],{"class":82},[73,6219,4218],{"class":284},[73,6221,4221],{"class":82},[73,6223,6225,6227,6229,6231,6233,6235,6237,6240,6242,6244,6246,6248,6250],{"class":75,"line":6224},150,[73,6226,3601],{"class":89},[73,6228,281],{"class":89},[73,6230,4559],{"class":284},[73,6232,1089],{"class":82},[73,6234,4218],{"class":284},[73,6236,5420],{"class":82},[73,6238,6239],{"class":686},"_",[73,6241,726],{"class":82},[73,6243,4813],{"class":686},[73,6245,3927],{"class":82},[73,6247,1766],{"class":89},[73,6249,5598],{"class":284},[73,6251,5271],{"class":82},[73,6253,6255],{"class":75,"line":6254},151,[73,6256,2984],{"class":82},[73,6258,6260],{"class":75,"line":6259},152,[73,6261,746],{"class":82},[73,6263,6265],{"class":75,"line":6264},153,[73,6266,437],{"emptyLinePlaceholder":436},[73,6268,6270,6273,6275,6277,6280,6282,6284],{"class":75,"line":6269},154,[73,6271,6272],{"class":82},"MyPromise.",[73,6274,1800],{"class":284},[73,6276,496],{"class":82},[73,6278,6279],{"class":79},"10",[73,6281,735],{"class":82},[73,6283,1806],{"class":284},[73,6285,3907],{"class":82},[73,6287,6289,6291,6293,6295,6297,6299,6301,6303,6306,6309],{"class":75,"line":6288},155,[73,6290,2623],{"class":82},[73,6292,4943],{"class":686},[73,6294,3927],{"class":82},[73,6296,1766],{"class":89},[73,6298,1769],{"class":82},[73,6300,758],{"class":284},[73,6302,496],{"class":82},[73,6304,6305],{"class":992},"'fulfilled'",[73,6307,6308],{"class":82},", v),   ",[73,6310,6311],{"class":291},"\u002F\u002F fulfilled 10\n",[73,6313,6315,6317,6319,6321,6323,6325,6327,6329,6332],{"class":75,"line":6314},156,[73,6316,2623],{"class":82},[73,6318,4971],{"class":686},[73,6320,3927],{"class":82},[73,6322,1766],{"class":89},[73,6324,1769],{"class":82},[73,6326,758],{"class":284},[73,6328,496],{"class":82},[73,6330,6331],{"class":992},"'rejected'",[73,6333,6334],{"class":82},", r)\n",[73,6336,6338],{"class":75,"line":6337},157,[73,6339,3111],{"class":82},[10,6341,6342],{},"await就是专门为Promise设计的，我们一般喜欢await x 这样来使用，如果x不是thenable，就会直接返回x，如果x是thenable，就会等它敲定，比如fulfilled返回成功值，rejected跑出拒绝原因。因此await不要求x是Promise实例，只要有then方法就行，说白了，就是认定鸭子类型。",[14,6344,6345],{"id":6345},"原型链",[10,6347,6348],{},"原型链的最初设计目的是为了用最少的机制来解决几个问题，Brendan Eich 1995年设计js的时候，是让对象能够借用另一个对象的方法和属性，而不需要每个对象都复制一份。原型链的本质就是委托，当你访问b.greet的时候b自己没有，就会委托给它的原型a去找，这是一种运行时动态查找，而不是编译器的类继承。",[10,6350,6351],{},"Brendan Eich收Self语言影响，核心思想是不需要类，对象可以直接从对象继承。这个就和传统OOP倾向的语言比如Java\u002FC++不一样了。Self\u002FJS的原型模型那就是： 对象 -> 对象 -> 对象。继承关系在对象之间定义，没有类中间层，每个对象都可以有自己的原型，可以动态修改。",[10,6353,6354],{},"所以，完全可以得出一个结论： js选择原型，是因为更加简单，更加灵活，更加适合脚本语言。这样就可以解决好几个问题：",[10,6356,6357],{},"1是内存效率问题，通过千万个实例可以共享一个函数，而不是每个都复制一份。2是动态性，原型链本来就是运行时查找，改了原型，所有实例都会立即收到影响，这个是类继承做不到的。",[10,6359,6360],{},"es5之前，js是没有class语法的，定义类的方式就是构造函数+原型。es6之后引入class作为了关键字和语法糖。但是到现在都没有interface关键字，因为js是动态语言，运行时才检查类型，不需要接口作为编译器约束。",[10,6362,6363,6366,6367,6369,6370,6372,6373,6376,6377,24,6384,6387],{},[21,6364,6365],{},"每个函数","都有一个 ",[26,6368,487],{}," 属性，指向一个对象，",[26,6371,487],{}," 是",[21,6374,6375],{},"函数才有的属性","，它的作用是：",[21,6378,6379,6380,6383],{},"当这个函数被用作构造函数（",[26,6381,6382],{},"new Foo()","）时，新对象的原型会指向它。",[21,6385,6386],{},"proto__就是每个对象内部的一个槽位，叫做[[Prototype]]，这个指向它的原型对象，访问方式是通过__proto","，或者Object.getPrototypeOf方法。 __proto__是对象才有的属性，指向继承。",[10,6389,6390,6391,2154],{},"默认情况下，",[26,6392,6393],{},"Foo.prototype.constructor === Foo",[64,6395,6397],{"className":1157,"code":6396,"language":1159,"meta":69,"style":69},"function Foo() {}\nFoo.prototype.constructor === Foo   \u002F\u002F true\n",[26,6398,6399,6407],{"__ignoreMap":69},[73,6400,6401,6403,6405],{"class":75,"line":76},[73,6402,356],{"class":89},[73,6404,2484],{"class":284},[73,6406,2334],{"class":82},[73,6408,6409,6412,6414,6416,6418,6420,6423,6426],{"class":75,"line":102},[73,6410,6411],{"class":79},"Foo",[73,6413,484],{"class":82},[73,6415,487],{"class":79},[73,6417,484],{"class":82},[73,6419,3825],{"class":79},[73,6421,6422],{"class":89}," ===",[73,6424,6425],{"class":82}," Foo   ",[73,6427,6428],{"class":291},"\u002F\u002F true\n",[10,6430,6431,6433],{},[26,6432,3825],{}," 让实例能反向找到\"创建我的构造函数\"。",[10,6435,6436],{},"还记得我们之前提到过的类型检测方法吗：",[64,6438,6439],{"className":1157,"code":474,"language":1159,"meta":69,"style":69},[26,6440,6441,6463,6485,6501,6523,6539,6559],{"__ignoreMap":69},[73,6442,6443,6445,6447,6449,6451,6453,6455,6457,6459,6461],{"class":75,"line":76},[73,6444,481],{"class":79},[73,6446,484],{"class":82},[73,6448,487],{"class":79},[73,6450,490],{"class":82},[73,6452,493],{"class":284},[73,6454,496],{"class":82},[73,6456,389],{"class":89},[73,6458,285],{"class":284},[73,6460,503],{"class":82},[73,6462,506],{"class":291},[73,6464,6465,6467,6469,6471,6473,6475,6477,6479,6481,6483],{"class":75,"line":102},[73,6466,481],{"class":79},[73,6468,484],{"class":82},[73,6470,487],{"class":79},[73,6472,490],{"class":82},[73,6474,493],{"class":284},[73,6476,496],{"class":82},[73,6478,389],{"class":89},[73,6480,333],{"class":284},[73,6482,503],{"class":82},[73,6484,529],{"class":291},[73,6486,6487,6489,6491,6493,6495,6497,6499],{"class":75,"line":120},[73,6488,481],{"class":79},[73,6490,484],{"class":82},[73,6492,487],{"class":79},[73,6494,490],{"class":82},[73,6496,493],{"class":284},[73,6498,544],{"class":82},[73,6500,547],{"class":291},[73,6502,6503,6505,6507,6509,6511,6513,6515,6517,6519,6521],{"class":75,"line":139},[73,6504,481],{"class":79},[73,6506,484],{"class":82},[73,6508,487],{"class":79},[73,6510,490],{"class":82},[73,6512,493],{"class":284},[73,6514,496],{"class":82},[73,6516,389],{"class":89},[73,6518,319],{"class":284},[73,6520,568],{"class":82},[73,6522,571],{"class":291},[73,6524,6525,6527,6529,6531,6533,6535,6537],{"class":75,"line":159},[73,6526,481],{"class":79},[73,6528,484],{"class":82},[73,6530,487],{"class":79},[73,6532,490],{"class":82},[73,6534,493],{"class":284},[73,6536,586],{"class":82},[73,6538,589],{"class":291},[73,6540,6541,6543,6545,6547,6549,6551,6553,6555,6557],{"class":75,"line":178},[73,6542,481],{"class":79},[73,6544,484],{"class":82},[73,6546,487],{"class":79},[73,6548,490],{"class":82},[73,6550,493],{"class":284},[73,6552,496],{"class":82},[73,6554,606],{"class":79},[73,6556,609],{"class":82},[73,6558,612],{"class":291},[73,6560,6561,6563,6565,6567,6569,6571,6573,6575,6577],{"class":75,"line":204},[73,6562,481],{"class":79},[73,6564,484],{"class":82},[73,6566,487],{"class":79},[73,6568,490],{"class":82},[73,6570,493],{"class":284},[73,6572,496],{"class":82},[73,6574,629],{"class":79},[73,6576,632],{"class":82},[73,6578,635],{"class":291},[10,6580,6581],{},"这里可以发现Object本身就是函数，所以他有prototype，这个也很有趣，Object既是函数，是一个构造函数，我们可以断定的是Object.prototype是所有普通对象的原型链顶端：",[64,6583,6585],{"className":1157,"code":6584,"language":1159,"meta":69,"style":69},"const obj = {};\nobj.__proto__ === Object.prototype   \u002F\u002F true\n\nObject.getPrototypeOf(obj) === Object.prototype   \u002F\u002F true\n\n`Object.prototype` 上挂着所有对象共享的方法：\n\nObject.prototype.toString\nObject.prototype.hasOwnProperty\nObject.prototype.valueOf\nObject.prototype.isPrototypeOf\nObject.prototype.propertyIsEnumerable\nObject.prototype.toLocaleString\n\nObject.prototype.constructor === Object \u002F\u002F true , constructor也是指向Object自己\n",[26,6586,6587,6598,6616,6620,6641,6645,6653,6657,6668,6679,6690,6701,6712,6723,6727],{"__ignoreMap":69},[73,6588,6589,6591,6593,6595],{"class":75,"line":76},[73,6590,423],{"class":89},[73,6592,2519],{"class":79},[73,6594,90],{"class":89},[73,6596,6597],{"class":82}," {};\n",[73,6599,6600,6603,6605,6607,6609,6611,6613],{"class":75,"line":102},[73,6601,6602],{"class":82},"obj.",[73,6604,3802],{"class":79},[73,6606,6422],{"class":89},[73,6608,704],{"class":79},[73,6610,484],{"class":82},[73,6612,487],{"class":79},[73,6614,6615],{"class":291},"   \u002F\u002F true\n",[73,6617,6618],{"class":75,"line":120},[73,6619,437],{"emptyLinePlaceholder":436},[73,6621,6622,6625,6628,6631,6633,6635,6637,6639],{"class":75,"line":139},[73,6623,6624],{"class":82},"Object.",[73,6626,6627],{"class":284},"getPrototypeOf",[73,6629,6630],{"class":82},"(obj) ",[73,6632,3757],{"class":89},[73,6634,704],{"class":79},[73,6636,484],{"class":82},[73,6638,487],{"class":79},[73,6640,6615],{"class":291},[73,6642,6643],{"class":75,"line":159},[73,6644,437],{"emptyLinePlaceholder":436},[73,6646,6647,6650],{"class":75,"line":178},[73,6648,6649],{"class":992},"`Object.prototype`",[73,6651,6652],{"class":82}," 上挂着所有对象共享的方法：\n",[73,6654,6655],{"class":75,"line":204},[73,6656,437],{"emptyLinePlaceholder":436},[73,6658,6659,6661,6663,6665],{"class":75,"line":1198},[73,6660,481],{"class":79},[73,6662,484],{"class":82},[73,6664,487],{"class":79},[73,6666,6667],{"class":82},".toString\n",[73,6669,6670,6672,6674,6676],{"class":75,"line":1203},[73,6671,481],{"class":79},[73,6673,484],{"class":82},[73,6675,487],{"class":79},[73,6677,6678],{"class":82},".hasOwnProperty\n",[73,6680,6681,6683,6685,6687],{"class":75,"line":1209},[73,6682,481],{"class":79},[73,6684,484],{"class":82},[73,6686,487],{"class":79},[73,6688,6689],{"class":82},".valueOf\n",[73,6691,6692,6694,6696,6698],{"class":75,"line":1215},[73,6693,481],{"class":79},[73,6695,484],{"class":82},[73,6697,487],{"class":79},[73,6699,6700],{"class":82},".isPrototypeOf\n",[73,6702,6703,6705,6707,6709],{"class":75,"line":1221},[73,6704,481],{"class":79},[73,6706,484],{"class":82},[73,6708,487],{"class":79},[73,6710,6711],{"class":82},".propertyIsEnumerable\n",[73,6713,6714,6716,6718,6720],{"class":75,"line":1227},[73,6715,481],{"class":79},[73,6717,484],{"class":82},[73,6719,487],{"class":79},[73,6721,6722],{"class":82},".toLocaleString\n",[73,6724,6725],{"class":75,"line":1233},[73,6726,437],{"emptyLinePlaceholder":436},[73,6728,6729,6731,6733,6735,6737,6739,6741,6744],{"class":75,"line":1899},[73,6730,481],{"class":79},[73,6732,484],{"class":82},[73,6734,487],{"class":79},[73,6736,484],{"class":82},[73,6738,3825],{"class":79},[73,6740,6422],{"class":89},[73,6742,6743],{"class":82}," Object ",[73,6745,6746],{"class":291},"\u002F\u002F true , constructor也是指向Object自己\n",[10,6748,6749],{},"instanceof 的原理是： obj instanceof Foo 检查 Foo.prototype 是否在obj的原型链上，你甚至也可以手动去实现：",[64,6751,6753],{"className":1157,"code":6752,"language":1159,"meta":69,"style":69},"function myInstanceof(obj, Constructor) {\n    let proto = Object.getPrototypeOf(obj);\n    while (proto !== null) {\n        if (proto === Constructor.prototype) return true;\n        proto = Object.getPrototypeOf(proto);\n    }\n    return false;\n}\n",[26,6754,6755,6773,6789,6803,6827,6841,6845,6854],{"__ignoreMap":69},[73,6756,6757,6759,6762,6764,6767,6769,6771],{"class":75,"line":76},[73,6758,356],{"class":89},[73,6760,6761],{"class":284}," myInstanceof",[73,6763,496],{"class":82},[73,6765,6766],{"class":686},"obj",[73,6768,726],{"class":82},[73,6770,3674],{"class":686},[73,6772,696],{"class":82},[73,6774,6775,6778,6781,6783,6785,6787],{"class":75,"line":102},[73,6776,6777],{"class":89},"    let",[73,6779,6780],{"class":82}," proto ",[73,6782,989],{"class":89},[73,6784,3701],{"class":82},[73,6786,6627],{"class":284},[73,6788,3139],{"class":82},[73,6790,6791,6794,6797,6799,6801],{"class":75,"line":120},[73,6792,6793],{"class":89},"    while",[73,6795,6796],{"class":82}," (proto ",[73,6798,2864],{"class":89},[73,6800,344],{"class":79},[73,6802,696],{"class":82},[73,6804,6805,6807,6809,6811,6814,6816,6818,6820,6822,6825],{"class":75,"line":139},[73,6806,4748],{"class":89},[73,6808,6796],{"class":82},[73,6810,3757],{"class":89},[73,6812,6813],{"class":79}," Constructor",[73,6815,484],{"class":82},[73,6817,487],{"class":79},[73,6819,3927],{"class":82},[73,6821,3776],{"class":89},[73,6823,6824],{"class":79}," true",[73,6826,1382],{"class":82},[73,6828,6829,6832,6834,6836,6838],{"class":75,"line":159},[73,6830,6831],{"class":82},"        proto ",[73,6833,989],{"class":89},[73,6835,3701],{"class":82},[73,6837,6627],{"class":284},[73,6839,6840],{"class":82},"(proto);\n",[73,6842,6843],{"class":75,"line":178},[73,6844,2984],{"class":82},[73,6846,6847,6849,6852],{"class":75,"line":204},[73,6848,3001],{"class":89},[73,6850,6851],{"class":79}," false",[73,6853,1382],{"class":82},[73,6855,6856],{"class":75,"line":1198},[73,6857,746],{"class":82},[10,6859,6860,6861,6864],{},"所以函数是一种特殊的对象，之所以能被调用是因为有 ",[26,6862,6863],{},"[[Call]]","，同时具备对象的一切能力，能挂载属性，有原型，能作为参数传递，函数既可以被当作普通函数，也可以被当成构造函数。",[10,6866,6867],{},[21,6868,6869,6870,6872],{},"两个 ",[26,6871,3825],{},"，别混：",[780,6874,6875,6888],{},[783,6876,6877],{},[786,6878,6879,6882,6885],{},[789,6880,6881],{},"表达式",[789,6883,6884],{},"结果",[789,6886,6887],{},"含义",[799,6889,6890,6910,6929],{},[786,6891,6892,6897,6901],{},[804,6893,6894],{},[26,6895,6896],{},"Foo.constructor",[804,6898,6899],{},[26,6900,2799],{},[804,6902,6903,6905,6906,6909],{},[26,6904,6411],{}," 这个函数",[21,6907,6908],{},"对象","由谁创建",[786,6911,6912,6917,6921],{},[804,6913,6914],{},[26,6915,6916],{},"Foo.prototype.constructor",[804,6918,6919],{},[26,6920,6411],{},[804,6922,6923,6925,6926,6909],{},[26,6924,6411],{}," 的",[21,6927,6928],{},"实例",[786,6930,6931,6934,6936],{},[804,6932,6933],{},"new Foo()执行的就是Foo这个函数，而不是Foo.constructor。",[804,6935],{},[804,6937],{},[14,6939,6940],{"id":6940},"数组可以调用的方法",[10,6942,6943],{},"数组可以调用的函数分为实例方法，挂载到Array.prototype上的，数组可以直接使用。静态方法是挂载在Array的构造函数上的，通过Array.xxx调用。",[10,6945,6946],{},"实例方法：",[780,6948,6949,6959],{},[783,6950,6951],{},[786,6952,6953,6956],{},[789,6954,6955],{},"方法",[789,6957,6958],{},"作用",[799,6960,6961,6971,6981,6991,7001,7011,7021,7031,7041],{},[786,6962,6963,6968],{},[804,6964,6965],{},[26,6966,6967],{},"push(...items)",[804,6969,6970],{},"末尾添加，返回新长度",[786,6972,6973,6978],{},[804,6974,6975],{},[26,6976,6977],{},"pop()",[804,6979,6980],{},"删除末尾，返回被删元素",[786,6982,6983,6988],{},[804,6984,6985],{},[26,6986,6987],{},"unshift(...items)",[804,6989,6990],{},"开头添加，返回新长度",[786,6992,6993,6998],{},[804,6994,6995],{},[26,6996,6997],{},"shift()",[804,6999,7000],{},"删除开头，返回被删元素",[786,7002,7003,7008],{},[804,7004,7005],{},[26,7006,7007],{},"splice(start, deleteCount, ...items)",[804,7009,7010],{},"任意位置增删，返回被删元素数组",[786,7012,7013,7018],{},[804,7014,7015],{},[26,7016,7017],{},"reverse()",[804,7019,7020],{},"反转，返回原数组",[786,7022,7023,7028],{},[804,7024,7025],{},[26,7026,7027],{},"sort(compareFn?)",[804,7029,7030],{},"排序，返回原数组",[786,7032,7033,7038],{},[804,7034,7035],{},[26,7036,7037],{},"fill(value, start?, end?)",[804,7039,7040],{},"填充，返回原数组",[786,7042,7043,7048],{},[804,7044,7045],{},[26,7046,7047],{},"copyWithin(target, start?, end?)",[804,7049,7050],{},"内部复制，返回原数组",[780,7052,7053,7061],{},[783,7054,7055],{},[786,7056,7057,7059],{},[789,7058,6955],{},[789,7060,6958],{},[799,7062,7063,7073,7083,7093,7103,7113,7123,7133,7143,7153,7163,7173,7183,7193,7203,7213,7223,7233,7243,7253],{},[786,7064,7065,7070],{},[804,7066,7067],{},[26,7068,7069],{},"concat(...items)",[804,7071,7072],{},"合并，返回新数组",[786,7074,7075,7080],{},[804,7076,7077],{},[26,7078,7079],{},"slice(start?, end?)",[804,7081,7082],{},"截取，返回新数组",[786,7084,7085,7090],{},[804,7086,7087],{},[26,7088,7089],{},"join(sep?)",[804,7091,7092],{},"转字符串",[786,7094,7095,7100],{},[804,7096,7097],{},[26,7098,7099],{},"indexOf(item, from?)",[804,7101,7102],{},"找索引，找不到返回 -1",[786,7104,7105,7110],{},[804,7106,7107],{},[26,7108,7109],{},"lastIndexOf(item, from?)",[804,7111,7112],{},"从后找索引",[786,7114,7115,7120],{},[804,7116,7117],{},[26,7118,7119],{},"includes(item, from?)",[804,7121,7122],{},"是否包含，返回 boolean",[786,7124,7125,7130],{},[804,7126,7127],{},[26,7128,7129],{},"find(cb)",[804,7131,7132],{},"找第一个满足的元素",[786,7134,7135,7140],{},[804,7136,7137],{},[26,7138,7139],{},"findIndex(cb)",[804,7141,7142],{},"找第一个满足的索引",[786,7144,7145,7150],{},[804,7146,7147],{},[26,7148,7149],{},"findLast(cb)",[804,7151,7152],{},"从后找第一个满足的元素（ES2023）",[786,7154,7155,7160],{},[804,7156,7157],{},[26,7158,7159],{},"findLastIndex(cb)",[804,7161,7162],{},"从后找索引（ES2023）",[786,7164,7165,7170],{},[804,7166,7167],{},[26,7168,7169],{},"filter(cb)",[804,7171,7172],{},"过滤，返回新数组",[786,7174,7175,7180],{},[804,7176,7177],{},[26,7178,7179],{},"map(cb)",[804,7181,7182],{},"映射，返回新数组",[786,7184,7185,7190],{},[804,7186,7187],{},[26,7188,7189],{},"flat(depth?)",[804,7191,7192],{},"扁平化",[786,7194,7195,7200],{},[804,7196,7197],{},[26,7198,7199],{},"flatMap(cb)",[804,7201,7202],{},"map + flat",[786,7204,7205,7210],{},[804,7206,7207],{},[26,7208,7209],{},"at(index)",[804,7211,7212],{},"支持负数索引",[786,7214,7215,7220],{},[804,7216,7217],{},[26,7218,7219],{},"with(index, value)",[804,7221,7222],{},"返回替换后的新数组（ES2023）",[786,7224,7225,7230],{},[804,7226,7227],{},[26,7228,7229],{},"toReversed()",[804,7231,7232],{},"反转副本（ES2023）",[786,7234,7235,7240],{},[804,7236,7237],{},[26,7238,7239],{},"toSorted(cmp?)",[804,7241,7242],{},"排序副本（ES2023）",[786,7244,7245,7250],{},[804,7246,7247],{},[26,7248,7249],{},"toSpliced(...)",[804,7251,7252],{},"splice 副本（ES2023）",[786,7254,7255,7258],{},[804,7256,7257],{},"静态方法：",[804,7259],{},[780,7261,7262,7270],{},[783,7263,7264],{},[786,7265,7266,7268],{},[789,7267,6955],{},[789,7269,6958],{},[799,7271,7272,7282,7296,7306],{},[786,7273,7274,7279],{},[804,7275,7276],{},[26,7277,7278],{},"Array.from(iterable, mapFn?, thisArg?)",[804,7280,7281],{},"从类数组\u002F可迭代对象创建数组",[786,7283,7284,7289],{},[804,7285,7286],{},[26,7287,7288],{},"Array.fromAsync(iterable)",[804,7290,7291,7292,7295],{},"异步版 ",[26,7293,7294],{},"from","（ES2023）",[786,7297,7298,7303],{},[804,7299,7300],{},[26,7301,7302],{},"Array.of(...items)",[804,7304,7305],{},"用参数创建数组",[786,7307,7308,7313],{},[804,7309,7310],{},[26,7311,7312],{},"Array.isArray(x)",[804,7314,7315],{},"判断是否数组",[10,7317,7318,7320,7321,7324],{},[26,7319,373],{}," 是 ",[26,7322,7323],{},"ArrayConstructor"," ，这个可以在ts的lib.es5.d.ts里找，大致如下：",[64,7326,7328],{"className":1157,"code":7327,"language":1159,"meta":69,"style":69},"interface ArrayConstructor {\n    new (arrayLength?: number): any[];\n    new \u003CT>(arrayLength: number): T[];\n    new \u003CT>(...items: T[]): T[];\n    isArray(arg: any): arg is any[];\n    from\u003CT>(arrayLike: ArrayLike\u003CT>): T[];\n    of\u003CT>(...items: T[]): T[];\n    \u002F\u002F ...\n}\n\ndeclare var Array: ArrayConstructor;\n",[26,7329,7330,7339,7362,7387,7414,7442,7474,7501,7506,7510,7514],{"__ignoreMap":69},[73,7331,7332,7334,7337],{"class":75,"line":76},[73,7333,1363],{"class":89},[73,7335,7336],{"class":284}," ArrayConstructor",[73,7338,1369],{"class":82},[73,7340,7341,7343,7345,7348,7350,7353,7355,7357,7359],{"class":75,"line":102},[73,7342,2595],{"class":89},[73,7344,2224],{"class":82},[73,7346,7347],{"class":686},"arrayLength",[73,7349,3915],{"class":89},[73,7351,7352],{"class":79}," number",[73,7354,4316],{"class":82},[73,7356,690],{"class":89},[73,7358,2749],{"class":79},[73,7360,7361],{"class":82},"[];\n",[73,7363,7364,7366,7369,7371,7373,7375,7377,7379,7381,7383,7385],{"class":75,"line":120},[73,7365,2595],{"class":89},[73,7367,7368],{"class":82}," \u003C",[73,7370,4218],{"class":284},[73,7372,6133],{"class":82},[73,7374,7347],{"class":686},[73,7376,690],{"class":89},[73,7378,7352],{"class":79},[73,7380,4316],{"class":82},[73,7382,690],{"class":89},[73,7384,3893],{"class":284},[73,7386,7361],{"class":82},[73,7388,7389,7391,7393,7395,7397,7399,7402,7404,7406,7408,7410,7412],{"class":75,"line":139},[73,7390,2595],{"class":89},[73,7392,7368],{"class":82},[73,7394,4218],{"class":284},[73,7396,6133],{"class":82},[73,7398,2600],{"class":89},[73,7400,7401],{"class":686},"items",[73,7403,690],{"class":89},[73,7405,3893],{"class":284},[73,7407,2611],{"class":82},[73,7409,690],{"class":89},[73,7411,3893],{"class":284},[73,7413,7361],{"class":82},[73,7415,7416,7419,7421,7424,7426,7428,7430,7432,7435,7438,7440],{"class":75,"line":159},[73,7417,7418],{"class":284},"    isArray",[73,7420,496],{"class":82},[73,7422,7423],{"class":686},"arg",[73,7425,690],{"class":89},[73,7427,2749],{"class":79},[73,7429,4316],{"class":82},[73,7431,690],{"class":89},[73,7433,7434],{"class":686}," arg",[73,7436,7437],{"class":89}," is",[73,7439,2749],{"class":79},[73,7441,7361],{"class":82},[73,7443,7444,7447,7449,7451,7453,7456,7458,7461,7463,7465,7468,7470,7472],{"class":75,"line":178},[73,7445,7446],{"class":284},"    from",[73,7448,1089],{"class":82},[73,7450,4218],{"class":284},[73,7452,6133],{"class":82},[73,7454,7455],{"class":686},"arrayLike",[73,7457,690],{"class":89},[73,7459,7460],{"class":284}," ArrayLike",[73,7462,1089],{"class":82},[73,7464,4218],{"class":284},[73,7466,7467],{"class":82},">)",[73,7469,690],{"class":89},[73,7471,3893],{"class":284},[73,7473,7361],{"class":82},[73,7475,7476,7479,7481,7483,7485,7487,7489,7491,7493,7495,7497,7499],{"class":75,"line":204},[73,7477,7478],{"class":284},"    of",[73,7480,1089],{"class":82},[73,7482,4218],{"class":284},[73,7484,6133],{"class":82},[73,7486,2600],{"class":89},[73,7488,7401],{"class":686},[73,7490,690],{"class":89},[73,7492,3893],{"class":284},[73,7494,2611],{"class":82},[73,7496,690],{"class":89},[73,7498,3893],{"class":284},[73,7500,7361],{"class":82},[73,7502,7503],{"class":75,"line":1198},[73,7504,7505],{"class":291},"    \u002F\u002F ...\n",[73,7507,7508],{"class":75,"line":1203},[73,7509,746],{"class":82},[73,7511,7512],{"class":75,"line":1209},[73,7513,437],{"emptyLinePlaceholder":436},[73,7515,7516,7518,7520,7523,7525,7527],{"class":75,"line":1215},[73,7517,2666],{"class":89},[73,7519,2669],{"class":89},[73,7521,7522],{"class":82}," Array",[73,7524,690],{"class":89},[73,7526,7336],{"class":284},[73,7528,1382],{"class":82},[10,7530,7531],{},"Array是ArrayConstructor类型的变量，它同时是函数。push在Array.prototype上：",[64,7533,7535],{"className":1157,"code":7534,"language":1159,"meta":69,"style":69},"interface Array\u003CT> {\n    push(...items: T[]): number;\n    pop(): T | undefined;\n    map\u003CU>(cb: (v: T, i: number, arr: T[]) => U): U[];\n    \u002F\u002F ...\n}\n\ninterface ArrayConstructor {\n    \u002F\u002F 静态方法\n}\n\ndeclare var Array: ArrayConstructor;\n",[26,7536,7537,7549,7572,7590,7648,7652,7656,7660,7668,7673,7677,7681],{"__ignoreMap":69},[73,7538,7539,7541,7543,7545,7547],{"class":75,"line":76},[73,7540,1363],{"class":89},[73,7542,7522],{"class":284},[73,7544,1089],{"class":82},[73,7546,4218],{"class":284},[73,7548,4221],{"class":82},[73,7550,7551,7554,7556,7558,7560,7562,7564,7566,7568,7570],{"class":75,"line":102},[73,7552,7553],{"class":284},"    push",[73,7555,496],{"class":82},[73,7557,2600],{"class":89},[73,7559,7401],{"class":686},[73,7561,690],{"class":89},[73,7563,3893],{"class":284},[73,7565,2611],{"class":82},[73,7567,690],{"class":89},[73,7569,7352],{"class":79},[73,7571,1382],{"class":82},[73,7573,7574,7577,7580,7582,7584,7586,7588],{"class":75,"line":120},[73,7575,7576],{"class":284},"    pop",[73,7578,7579],{"class":82},"()",[73,7581,690],{"class":89},[73,7583,3893],{"class":284},[73,7585,4059],{"class":89},[73,7587,4246],{"class":79},[73,7589,1382],{"class":82},[73,7591,7592,7595,7597,7600,7602,7605,7607,7609,7611,7613,7615,7617,7620,7622,7624,7626,7629,7631,7633,7635,7637,7640,7642,7644,7646],{"class":75,"line":139},[73,7593,7594],{"class":284},"    map",[73,7596,1089],{"class":82},[73,7598,7599],{"class":284},"U",[73,7601,6133],{"class":82},[73,7603,7604],{"class":284},"cb",[73,7606,690],{"class":89},[73,7608,2224],{"class":82},[73,7610,4943],{"class":686},[73,7612,690],{"class":89},[73,7614,3893],{"class":284},[73,7616,726],{"class":82},[73,7618,7619],{"class":686},"i",[73,7621,690],{"class":89},[73,7623,7352],{"class":79},[73,7625,726],{"class":82},[73,7627,7628],{"class":686},"arr",[73,7630,690],{"class":89},[73,7632,3893],{"class":284},[73,7634,2777],{"class":82},[73,7636,1766],{"class":89},[73,7638,7639],{"class":284}," U",[73,7641,4316],{"class":82},[73,7643,690],{"class":89},[73,7645,7639],{"class":284},[73,7647,7361],{"class":82},[73,7649,7650],{"class":75,"line":159},[73,7651,7505],{"class":291},[73,7653,7654],{"class":75,"line":178},[73,7655,746],{"class":82},[73,7657,7658],{"class":75,"line":204},[73,7659,437],{"emptyLinePlaceholder":436},[73,7661,7662,7664,7666],{"class":75,"line":1198},[73,7663,1363],{"class":89},[73,7665,7336],{"class":284},[73,7667,1369],{"class":82},[73,7669,7670],{"class":75,"line":1203},[73,7671,7672],{"class":291},"    \u002F\u002F 静态方法\n",[73,7674,7675],{"class":75,"line":1209},[73,7676,746],{"class":82},[73,7678,7679],{"class":75,"line":1215},[73,7680,437],{"emptyLinePlaceholder":436},[73,7682,7683,7685,7687,7689,7691,7693],{"class":75,"line":1221},[73,7684,2666],{"class":89},[73,7686,2669],{"class":89},[73,7688,7522],{"class":82},[73,7690,690],{"class":89},[73,7692,7336],{"class":284},[73,7694,1382],{"class":82},[10,7696,7697,7698,7701,7702,7704,7705,7707],{},"可以看到push是定义在",[26,7699,7700],{},"Array\u003CT>","上的，对应Array.prototype上，所有数组实例共享。",[73,7703],{},"或者new Array()都可以得到Array实例。",[73,7706],{},"是语法糖，或者严格来说是数组字面量，由规范里的ArrayLiteral生产式定义。两者创建的对象原型链完全一样。",[14,7709,7710],{"id":7710},"生成器与迭代器",[10,7712,7713],{},"[[生成器与迭代器]]",[14,7715,7716],{"id":7716},"流式操作",[10,7718,7719,7720,7723,7724,45,7727,45,7730,7733,7734],{},"流式操作远不止“读取大文件”。围绕 ",[21,7721,7722],{},"Web Streams API","（",[26,7725,7726],{},"ReadableStream",[26,7728,7729],{},"WritableStream",[26,7731,7732],{},"TransformStream","），可以构建出一整套",[21,7735,7736],{},"数据处理管道",[10,7738,7739],{},"比如说，读取视频文件，你可以把流接到目标：",[64,7741,7743],{"className":1157,"code":7742,"language":1159,"meta":69,"style":69},"const response = await fetch('\u002Fvideo.mp4');\nconst writable = new WritableStream({\n    write(chunk) {\n        console.log('收到', chunk.length, '字节');\n    }\n});\n\nawait response.body.pipeTo(writable);\n",[26,7744,7745,7765,7782,7794,7818,7822,7827,7831],{"__ignoreMap":69},[73,7746,7747,7749,7752,7754,7756,7758,7760,7763],{"class":75,"line":76},[73,7748,423],{"class":89},[73,7750,7751],{"class":79}," response",[73,7753,90],{"class":89},[73,7755,1478],{"class":89},[73,7757,1559],{"class":284},[73,7759,496],{"class":82},[73,7761,7762],{"class":992},"'\u002Fvideo.mp4'",[73,7764,3111],{"class":82},[73,7766,7767,7769,7772,7774,7776,7779],{"class":75,"line":102},[73,7768,423],{"class":89},[73,7770,7771],{"class":79}," writable",[73,7773,90],{"class":89},[73,7775,281],{"class":89},[73,7777,7778],{"class":284}," WritableStream",[73,7780,7781],{"class":82},"({\n",[73,7783,7784,7787,7789,7792],{"class":75,"line":120},[73,7785,7786],{"class":284},"    write",[73,7788,496],{"class":82},[73,7790,7791],{"class":686},"chunk",[73,7793,696],{"class":82},[73,7795,7796,7798,7800,7802,7805,7808,7811,7813,7816],{"class":75,"line":139},[73,7797,3092],{"class":82},[73,7799,758],{"class":284},[73,7801,496],{"class":82},[73,7803,7804],{"class":992},"'收到'",[73,7806,7807],{"class":82},", chunk.",[73,7809,7810],{"class":79},"length",[73,7812,726],{"class":82},[73,7814,7815],{"class":992},"'字节'",[73,7817,3111],{"class":82},[73,7819,7820],{"class":75,"line":159},[73,7821,2984],{"class":82},[73,7823,7824],{"class":75,"line":178},[73,7825,7826],{"class":82},"});\n",[73,7828,7829],{"class":75,"line":204},[73,7830,437],{"emptyLinePlaceholder":436},[73,7832,7833,7835,7838,7841],{"class":75,"line":1198},[73,7834,929],{"class":89},[73,7836,7837],{"class":82}," response.body.",[73,7839,7840],{"class":284},"pipeTo",[73,7842,7843],{"class":82},"(writable);\n",[10,7845,7846],{},"流可以经过转换器，body有个方法叫做pipeThrough，能够把字节转换为字符串，字符串转换为大写：",[64,7848,7850],{"className":1157,"code":7849,"language":1159,"meta":69,"style":69},"const response = await fetch('\u002Fdata.txt');\nconst stream = response.body\n    .pipeThrough(new TextDecoderStream())      \u002F\u002F 字节 → 字符串\n    .pipeThrough(new TransformStream({         \u002F\u002F 字符串 → 大写\n        transform(chunk, controller) {\n            controller.enqueue(chunk.toUpperCase());\n        }\n    }));\n\nfor await (const chunk of stream) {\n    console.log(chunk);\n}\n",[26,7851,7852,7871,7883,7903,7922,7938,7955,7959,7964,7968,7986,7995],{"__ignoreMap":69},[73,7853,7854,7856,7858,7860,7862,7864,7866,7869],{"class":75,"line":76},[73,7855,423],{"class":89},[73,7857,7751],{"class":79},[73,7859,90],{"class":89},[73,7861,1478],{"class":89},[73,7863,1559],{"class":284},[73,7865,496],{"class":82},[73,7867,7868],{"class":992},"'\u002Fdata.txt'",[73,7870,3111],{"class":82},[73,7872,7873,7875,7878,7880],{"class":75,"line":102},[73,7874,423],{"class":89},[73,7876,7877],{"class":79}," stream",[73,7879,90],{"class":89},[73,7881,7882],{"class":82}," response.body\n",[73,7884,7885,7888,7891,7893,7895,7898,7900],{"class":75,"line":120},[73,7886,7887],{"class":82},"    .",[73,7889,7890],{"class":284},"pipeThrough",[73,7892,496],{"class":82},[73,7894,389],{"class":89},[73,7896,7897],{"class":284}," TextDecoderStream",[73,7899,503],{"class":82},[73,7901,7902],{"class":291},"\u002F\u002F 字节 → 字符串\n",[73,7904,7905,7907,7909,7911,7913,7916,7919],{"class":75,"line":139},[73,7906,7887],{"class":82},[73,7908,7890],{"class":284},[73,7910,496],{"class":82},[73,7912,389],{"class":89},[73,7914,7915],{"class":284}," TransformStream",[73,7917,7918],{"class":82},"({         ",[73,7920,7921],{"class":291},"\u002F\u002F 字符串 → 大写\n",[73,7923,7924,7927,7929,7931,7933,7936],{"class":75,"line":159},[73,7925,7926],{"class":284},"        transform",[73,7928,496],{"class":82},[73,7930,7791],{"class":686},[73,7932,726],{"class":82},[73,7934,7935],{"class":686},"controller",[73,7937,696],{"class":82},[73,7939,7940,7943,7946,7949,7952],{"class":75,"line":178},[73,7941,7942],{"class":82},"            controller.",[73,7944,7945],{"class":284},"enqueue",[73,7947,7948],{"class":82},"(chunk.",[73,7950,7951],{"class":284},"toUpperCase",[73,7953,7954],{"class":82},"());\n",[73,7956,7957],{"class":75,"line":204},[73,7958,4857],{"class":82},[73,7960,7961],{"class":75,"line":1198},[73,7962,7963],{"class":82},"    }));\n",[73,7965,7966],{"class":75,"line":1203},[73,7967,437],{"emptyLinePlaceholder":436},[73,7969,7970,7972,7974,7976,7978,7981,7983],{"class":75,"line":1209},[73,7971,2221],{"class":89},[73,7973,1478],{"class":89},[73,7975,2224],{"class":82},[73,7977,423],{"class":89},[73,7979,7980],{"class":79}," chunk",[73,7982,5096],{"class":89},[73,7984,7985],{"class":82}," stream) {\n",[73,7987,7988,7990,7992],{"class":75,"line":1215},[73,7989,2089],{"class":82},[73,7991,758],{"class":284},[73,7993,7994],{"class":82},"(chunk);\n",[73,7996,7997],{"class":75,"line":1221},[73,7998,746],{"class":82},[10,8000,8001],{},"你甚至可以用tee把流直接一分为2交给两个消费者：",[64,8003,8005],{"className":1157,"code":8004,"language":1159,"meta":69,"style":69},"const response = await fetch('\u002Fdata');\nconst [stream1, stream2] = response.body.tee();\n\n\u002F\u002F 两个消费者同时处理\nstream1.pipeTo(new WritableStream({ write(c) { \u002F* ... *\u002F } }));\nstream2.pipeTo(new WritableStream({ write(c) { \u002F* ... *\u002F } }));\n",[26,8006,8007,8026,8054,8058,8063,8096],{"__ignoreMap":69},[73,8008,8009,8011,8013,8015,8017,8019,8021,8024],{"class":75,"line":76},[73,8010,423],{"class":89},[73,8012,7751],{"class":79},[73,8014,90],{"class":89},[73,8016,1478],{"class":89},[73,8018,1559],{"class":284},[73,8020,496],{"class":82},[73,8022,8023],{"class":992},"'\u002Fdata'",[73,8025,3111],{"class":82},[73,8027,8028,8030,8033,8036,8038,8041,8044,8046,8048,8051],{"class":75,"line":102},[73,8029,423],{"class":89},[73,8031,8032],{"class":82}," [",[73,8034,8035],{"class":79},"stream1",[73,8037,726],{"class":82},[73,8039,8040],{"class":79},"stream2",[73,8042,8043],{"class":82},"] ",[73,8045,989],{"class":89},[73,8047,7837],{"class":82},[73,8049,8050],{"class":284},"tee",[73,8052,8053],{"class":82},"();\n",[73,8055,8056],{"class":75,"line":120},[73,8057,437],{"emptyLinePlaceholder":436},[73,8059,8060],{"class":75,"line":139},[73,8061,8062],{"class":291},"\u002F\u002F 两个消费者同时处理\n",[73,8064,8065,8068,8070,8072,8074,8076,8079,8082,8084,8087,8090,8093],{"class":75,"line":159},[73,8066,8067],{"class":82},"stream1.",[73,8069,7840],{"class":284},[73,8071,496],{"class":82},[73,8073,389],{"class":89},[73,8075,7778],{"class":284},[73,8077,8078],{"class":82},"({ ",[73,8080,8081],{"class":284},"write",[73,8083,496],{"class":82},[73,8085,8086],{"class":686},"c",[73,8088,8089],{"class":82},") { ",[73,8091,8092],{"class":291},"\u002F* ... *\u002F",[73,8094,8095],{"class":82}," } }));\n",[73,8097,8098,8101,8103,8105,8107,8109,8111,8113,8115,8117,8119,8121],{"class":75,"line":178},[73,8099,8100],{"class":82},"stream2.",[73,8102,7840],{"class":284},[73,8104,496],{"class":82},[73,8106,389],{"class":89},[73,8108,7778],{"class":284},[73,8110,8078],{"class":82},[73,8112,8081],{"class":284},[73,8114,496],{"class":82},[73,8116,8086],{"class":686},[73,8118,8089],{"class":82},[73,8120,8092],{"class":291},[73,8122,8095],{"class":82},[8124,8125,8126],"h4",{"id":8126},"常用场景",[10,8128,8129],{},"解压操作gz；",[64,8131,8133],{"className":1157,"code":8132,"language":1159,"meta":69,"style":69},"const response = await fetch('\u002Fdata.gz');\nconst stream = response.body\n    .pipeThrough(new DecompressionStream('gzip'));\n\nconst text = await new Response(stream).text();\nconsole.log(text);\n",[26,8134,8135,8154,8164,8184,8188,8211],{"__ignoreMap":69},[73,8136,8137,8139,8141,8143,8145,8147,8149,8152],{"class":75,"line":76},[73,8138,423],{"class":89},[73,8140,7751],{"class":79},[73,8142,90],{"class":89},[73,8144,1478],{"class":89},[73,8146,1559],{"class":284},[73,8148,496],{"class":82},[73,8150,8151],{"class":992},"'\u002Fdata.gz'",[73,8153,3111],{"class":82},[73,8155,8156,8158,8160,8162],{"class":75,"line":102},[73,8157,423],{"class":89},[73,8159,7877],{"class":79},[73,8161,90],{"class":89},[73,8163,7882],{"class":82},[73,8165,8166,8168,8170,8172,8174,8177,8179,8182],{"class":75,"line":120},[73,8167,7887],{"class":82},[73,8169,7890],{"class":284},[73,8171,496],{"class":82},[73,8173,389],{"class":89},[73,8175,8176],{"class":284}," DecompressionStream",[73,8178,496],{"class":82},[73,8180,8181],{"class":992},"'gzip'",[73,8183,5973],{"class":82},[73,8185,8186],{"class":75,"line":139},[73,8187,437],{"emptyLinePlaceholder":436},[73,8189,8190,8192,8195,8197,8199,8201,8204,8207,8209],{"class":75,"line":159},[73,8191,423],{"class":89},[73,8193,8194],{"class":79}," text",[73,8196,90],{"class":89},[73,8198,1478],{"class":89},[73,8200,281],{"class":89},[73,8202,8203],{"class":284}," Response",[73,8205,8206],{"class":82},"(stream).",[73,8208,2008],{"class":284},[73,8210,8053],{"class":82},[73,8212,8213,8215,8217],{"class":75,"line":178},[73,8214,755],{"class":82},[73,8216,758],{"class":284},[73,8218,8219],{"class":82},"(text);\n",[10,8221,8222],{},"压缩为gzip：",[64,8224,8226],{"className":1157,"code":8225,"language":1159,"meta":69,"style":69},"const stream = new Blob(['hello world'])\n    .stream()\n    .pipeThrough(new CompressionStream('gzip'));\n\nconst compressed = await new Response(stream).arrayBuffer();\n",[26,8227,8228,8250,8259,8278,8282],{"__ignoreMap":69},[73,8229,8230,8232,8234,8236,8238,8241,8244,8247],{"class":75,"line":76},[73,8231,423],{"class":89},[73,8233,7877],{"class":79},[73,8235,90],{"class":89},[73,8237,281],{"class":89},[73,8239,8240],{"class":284}," Blob",[73,8242,8243],{"class":82},"([",[73,8245,8246],{"class":992},"'hello world'",[73,8248,8249],{"class":82},"])\n",[73,8251,8252,8254,8257],{"class":75,"line":102},[73,8253,7887],{"class":82},[73,8255,8256],{"class":284},"stream",[73,8258,741],{"class":82},[73,8260,8261,8263,8265,8267,8269,8272,8274,8276],{"class":75,"line":120},[73,8262,7887],{"class":82},[73,8264,7890],{"class":284},[73,8266,496],{"class":82},[73,8268,389],{"class":89},[73,8270,8271],{"class":284}," CompressionStream",[73,8273,496],{"class":82},[73,8275,8181],{"class":992},[73,8277,5973],{"class":82},[73,8279,8280],{"class":75,"line":139},[73,8281,437],{"emptyLinePlaceholder":436},[73,8283,8284,8286,8289,8291,8293,8295,8297,8299,8302],{"class":75,"line":159},[73,8285,423],{"class":89},[73,8287,8288],{"class":79}," compressed",[73,8290,90],{"class":89},[73,8292,1478],{"class":89},[73,8294,281],{"class":89},[73,8296,8203],{"class":284},[73,8298,8206],{"class":82},[73,8300,8301],{"class":284},"arrayBuffer",[73,8303,8053],{"class":82},[10,8305,8306],{},"文本接编码；",[64,8308,8310],{"className":1157,"code":8309,"language":1159,"meta":69,"style":69},"const response = await fetch('\u002Fdata.txt');\nconst stream = response.body\n    .pipeThrough(new TextDecoderStream());\n\nfor await (const chunk of stream) {\n    console.log(chunk);  \u002F\u002F 字符串\n}\n\nconst stream = new ReadableStream({\n    start(controller) {\n        controller.enqueue('hello');\n        controller.enqueue('world');\n        controller.close();\n    }\n}).pipeThrough(new TextEncoderStream());\n",[26,8311,8312,8330,8340,8354,8358,8374,8386,8390,8394,8409,8420,8434,8447,8456,8460],{"__ignoreMap":69},[73,8313,8314,8316,8318,8320,8322,8324,8326,8328],{"class":75,"line":76},[73,8315,423],{"class":89},[73,8317,7751],{"class":79},[73,8319,90],{"class":89},[73,8321,1478],{"class":89},[73,8323,1559],{"class":284},[73,8325,496],{"class":82},[73,8327,7868],{"class":992},[73,8329,3111],{"class":82},[73,8331,8332,8334,8336,8338],{"class":75,"line":102},[73,8333,423],{"class":89},[73,8335,7877],{"class":79},[73,8337,90],{"class":89},[73,8339,7882],{"class":82},[73,8341,8342,8344,8346,8348,8350,8352],{"class":75,"line":120},[73,8343,7887],{"class":82},[73,8345,7890],{"class":284},[73,8347,496],{"class":82},[73,8349,389],{"class":89},[73,8351,7897],{"class":284},[73,8353,7954],{"class":82},[73,8355,8356],{"class":75,"line":139},[73,8357,437],{"emptyLinePlaceholder":436},[73,8359,8360,8362,8364,8366,8368,8370,8372],{"class":75,"line":159},[73,8361,2221],{"class":89},[73,8363,1478],{"class":89},[73,8365,2224],{"class":82},[73,8367,423],{"class":89},[73,8369,7980],{"class":79},[73,8371,5096],{"class":89},[73,8373,7985],{"class":82},[73,8375,8376,8378,8380,8383],{"class":75,"line":178},[73,8377,2089],{"class":82},[73,8379,758],{"class":284},[73,8381,8382],{"class":82},"(chunk);  ",[73,8384,8385],{"class":291},"\u002F\u002F 字符串\n",[73,8387,8388],{"class":75,"line":204},[73,8389,746],{"class":82},[73,8391,8392],{"class":75,"line":1198},[73,8393,437],{"emptyLinePlaceholder":436},[73,8395,8396,8398,8400,8402,8404,8407],{"class":75,"line":1203},[73,8397,423],{"class":89},[73,8399,7877],{"class":79},[73,8401,90],{"class":89},[73,8403,281],{"class":89},[73,8405,8406],{"class":284}," ReadableStream",[73,8408,7781],{"class":82},[73,8410,8411,8414,8416,8418],{"class":75,"line":1209},[73,8412,8413],{"class":284},"    start",[73,8415,496],{"class":82},[73,8417,7935],{"class":686},[73,8419,696],{"class":82},[73,8421,8422,8425,8427,8429,8432],{"class":75,"line":1215},[73,8423,8424],{"class":82},"        controller.",[73,8426,7945],{"class":284},[73,8428,496],{"class":82},[73,8430,8431],{"class":992},"'hello'",[73,8433,3111],{"class":82},[73,8435,8436,8438,8440,8442,8445],{"class":75,"line":1221},[73,8437,8424],{"class":82},[73,8439,7945],{"class":284},[73,8441,496],{"class":82},[73,8443,8444],{"class":992},"'world'",[73,8446,3111],{"class":82},[73,8448,8449,8451,8454],{"class":75,"line":1227},[73,8450,8424],{"class":82},[73,8452,8453],{"class":284},"close",[73,8455,8053],{"class":82},[73,8457,8458],{"class":75,"line":1233},[73,8459,2984],{"class":82},[73,8461,8462,8465,8467,8469,8471,8474],{"class":75,"line":1899},[73,8463,8464],{"class":82},"}).",[73,8466,7890],{"class":284},[73,8468,496],{"class":82},[73,8470,389],{"class":89},[73,8472,8473],{"class":284}," TextEncoderStream",[73,8475,7954],{"class":82},[8124,8477,8478],{"id":8478},"流式数据格式解析",[10,8480,8481],{},"NDJSON，每行有一个json:",[64,8483,8485],{"className":1157,"code":8484,"language":1159,"meta":69,"style":69},"async function* parseNDJSON(stream) {\n    const reader = stream\n        .pipeThrough(new TextDecoderStream())\n        .getReader();\n    let buffer = '';\n\n    while (true) {\n        const { done, value } = await reader.read();\n        if (done) break;\n        buffer += value;\n        const lines = buffer.split('\\n');\n        buffer = lines.pop();\n        for (const line of lines) {\n            if (line.trim()) yield JSON.parse(line);\n        }\n    }\n}\n\nconst response = await fetch('\u002Flogs.ndjson');\nfor await (const obj of parseNDJSON(response.body)) {\n    console.log(obj);\n}\n",[26,8486,8487,8503,8515,8531,8540,8554,8558,8568,8597,8609,8619,8646,8660,8676,8703,8707,8711,8715,8719,8738,8757,8765],{"__ignoreMap":69},[73,8488,8489,8491,8494,8497,8499,8501],{"class":75,"line":76},[73,8490,1522],{"class":89},[73,8492,8493],{"class":89}," function*",[73,8495,8496],{"class":284}," parseNDJSON",[73,8498,496],{"class":82},[73,8500,8256],{"class":686},[73,8502,696],{"class":82},[73,8504,8505,8507,8510,8512],{"class":75,"line":102},[73,8506,2076],{"class":89},[73,8508,8509],{"class":79}," reader",[73,8511,90],{"class":89},[73,8513,8514],{"class":82}," stream\n",[73,8516,8517,8520,8522,8524,8526,8528],{"class":75,"line":120},[73,8518,8519],{"class":82},"        .",[73,8521,7890],{"class":284},[73,8523,496],{"class":82},[73,8525,389],{"class":89},[73,8527,7897],{"class":284},[73,8529,8530],{"class":82},"())\n",[73,8532,8533,8535,8538],{"class":75,"line":139},[73,8534,8519],{"class":82},[73,8536,8537],{"class":284},"getReader",[73,8539,8053],{"class":82},[73,8541,8542,8544,8547,8549,8552],{"class":75,"line":159},[73,8543,6777],{"class":89},[73,8545,8546],{"class":82}," buffer ",[73,8548,989],{"class":89},[73,8550,8551],{"class":992}," ''",[73,8553,1382],{"class":82},[73,8555,8556],{"class":75,"line":178},[73,8557,437],{"emptyLinePlaceholder":436},[73,8559,8560,8562,8564,8566],{"class":75,"line":204},[73,8561,6793],{"class":89},[73,8563,2224],{"class":82},[73,8565,1439],{"class":79},[73,8567,696],{"class":82},[73,8569,8570,8572,8575,8578,8580,8582,8585,8587,8589,8592,8595],{"class":75,"line":1198},[73,8571,5046],{"class":89},[73,8573,8574],{"class":82}," { ",[73,8576,8577],{"class":79},"done",[73,8579,726],{"class":82},[73,8581,687],{"class":79},[73,8583,8584],{"class":82}," } ",[73,8586,989],{"class":89},[73,8588,1478],{"class":89},[73,8590,8591],{"class":82}," reader.",[73,8593,8594],{"class":284},"read",[73,8596,8053],{"class":82},[73,8598,8599,8601,8604,8607],{"class":75,"line":1203},[73,8600,4748],{"class":89},[73,8602,8603],{"class":82}," (done) ",[73,8605,8606],{"class":89},"break",[73,8608,1382],{"class":82},[73,8610,8611,8614,8617],{"class":75,"line":1209},[73,8612,8613],{"class":82},"        buffer ",[73,8615,8616],{"class":89},"+=",[73,8618,5035],{"class":82},[73,8620,8621,8623,8626,8628,8631,8634,8636,8639,8642,8644],{"class":75,"line":1215},[73,8622,5046],{"class":89},[73,8624,8625],{"class":79}," lines",[73,8627,90],{"class":89},[73,8629,8630],{"class":82}," buffer.",[73,8632,8633],{"class":284},"split",[73,8635,496],{"class":82},[73,8637,8638],{"class":992},"'",[73,8640,8641],{"class":79},"\\n",[73,8643,8638],{"class":992},[73,8645,3111],{"class":82},[73,8647,8648,8650,8652,8655,8658],{"class":75,"line":1221},[73,8649,8613],{"class":82},[73,8651,989],{"class":89},[73,8653,8654],{"class":82}," lines.",[73,8656,8657],{"class":284},"pop",[73,8659,8053],{"class":82},[73,8661,8662,8664,8666,8668,8671,8673],{"class":75,"line":1227},[73,8663,5086],{"class":89},[73,8665,2224],{"class":82},[73,8667,423],{"class":89},[73,8669,8670],{"class":79}," line",[73,8672,5096],{"class":89},[73,8674,8675],{"class":82}," lines) {\n",[73,8677,8678,8680,8683,8686,8689,8692,8695,8697,8700],{"class":75,"line":1233},[73,8679,5887],{"class":89},[73,8681,8682],{"class":82}," (line.",[73,8684,8685],{"class":284},"trim",[73,8687,8688],{"class":82},"()) ",[73,8690,8691],{"class":89},"yield",[73,8693,8694],{"class":79}," JSON",[73,8696,484],{"class":82},[73,8698,8699],{"class":284},"parse",[73,8701,8702],{"class":82},"(line);\n",[73,8704,8705],{"class":75,"line":1899},[73,8706,4857],{"class":82},[73,8708,8709],{"class":75,"line":1913},[73,8710,2984],{"class":82},[73,8712,8713],{"class":75,"line":1918},[73,8714,746],{"class":82},[73,8716,8717],{"class":75,"line":1927},[73,8718,437],{"emptyLinePlaceholder":436},[73,8720,8721,8723,8725,8727,8729,8731,8733,8736],{"class":75,"line":1935},[73,8722,423],{"class":89},[73,8724,7751],{"class":79},[73,8726,90],{"class":89},[73,8728,1478],{"class":89},[73,8730,1559],{"class":284},[73,8732,496],{"class":82},[73,8734,8735],{"class":992},"'\u002Flogs.ndjson'",[73,8737,3111],{"class":82},[73,8739,8740,8742,8744,8746,8748,8750,8752,8754],{"class":75,"line":1943},[73,8741,2221],{"class":89},[73,8743,1478],{"class":89},[73,8745,2224],{"class":82},[73,8747,423],{"class":89},[73,8749,2519],{"class":79},[73,8751,5096],{"class":89},[73,8753,8496],{"class":284},[73,8755,8756],{"class":82},"(response.body)) {\n",[73,8758,8759,8761,8763],{"class":75,"line":1952},[73,8760,2089],{"class":82},[73,8762,758],{"class":284},[73,8764,3139],{"class":82},[73,8766,8767],{"class":75,"line":1966},[73,8768,746],{"class":82},[10,8770,8771,8772,645,8775,8778,8779,8782],{},"SSE数据处理，sse服务器可以发送默认消息和自定义事件，消息没有event字段，浏览器默认按照message事件处理，客户端用",[26,8773,8774],{},"es.onmessage",[26,8776,8777],{},"es.addEventListener('message', ...)"," 接收。自定义事件有event字段，指定事件类型，- 客户端用 ",[26,8780,8781],{},"es.addEventListener('eventName', ...)"," 接收。",[64,8784,8786],{"className":1157,"code":8785,"language":1159,"meta":69,"style":69},"async function* parseSSE(stream) {\n    const reader = stream\n        .pipeThrough(new TextDecoderStream())\n        .getReader();\n    let buffer = '';\n\n    while (true) {\n        const { done, value } = await reader.read();\n        if (done) break;\n        buffer += value;\n        const events = buffer.split('\\n\\n');\n        buffer = events.pop();\n        for (const event of events) {\n            const data = event\n                .split('\\n')\n                .filter(l => l.startsWith('data:'))\n                .map(l => l.slice(5).trim())\n                .join('\\n');\n            yield data;\n        }\n    }\n}\n",[26,8787,8788,8803,8813,8827,8835,8847,8851,8861,8885,8895,8903,8927,8940,8956,8967,8984,9013,9041,9058,9066,9070,9074],{"__ignoreMap":69},[73,8789,8790,8792,8794,8797,8799,8801],{"class":75,"line":76},[73,8791,1522],{"class":89},[73,8793,8493],{"class":89},[73,8795,8796],{"class":284}," parseSSE",[73,8798,496],{"class":82},[73,8800,8256],{"class":686},[73,8802,696],{"class":82},[73,8804,8805,8807,8809,8811],{"class":75,"line":102},[73,8806,2076],{"class":89},[73,8808,8509],{"class":79},[73,8810,90],{"class":89},[73,8812,8514],{"class":82},[73,8814,8815,8817,8819,8821,8823,8825],{"class":75,"line":120},[73,8816,8519],{"class":82},[73,8818,7890],{"class":284},[73,8820,496],{"class":82},[73,8822,389],{"class":89},[73,8824,7897],{"class":284},[73,8826,8530],{"class":82},[73,8828,8829,8831,8833],{"class":75,"line":139},[73,8830,8519],{"class":82},[73,8832,8537],{"class":284},[73,8834,8053],{"class":82},[73,8836,8837,8839,8841,8843,8845],{"class":75,"line":159},[73,8838,6777],{"class":89},[73,8840,8546],{"class":82},[73,8842,989],{"class":89},[73,8844,8551],{"class":992},[73,8846,1382],{"class":82},[73,8848,8849],{"class":75,"line":178},[73,8850,437],{"emptyLinePlaceholder":436},[73,8852,8853,8855,8857,8859],{"class":75,"line":204},[73,8854,6793],{"class":89},[73,8856,2224],{"class":82},[73,8858,1439],{"class":79},[73,8860,696],{"class":82},[73,8862,8863,8865,8867,8869,8871,8873,8875,8877,8879,8881,8883],{"class":75,"line":1198},[73,8864,5046],{"class":89},[73,8866,8574],{"class":82},[73,8868,8577],{"class":79},[73,8870,726],{"class":82},[73,8872,687],{"class":79},[73,8874,8584],{"class":82},[73,8876,989],{"class":89},[73,8878,1478],{"class":89},[73,8880,8591],{"class":82},[73,8882,8594],{"class":284},[73,8884,8053],{"class":82},[73,8886,8887,8889,8891,8893],{"class":75,"line":1203},[73,8888,4748],{"class":89},[73,8890,8603],{"class":82},[73,8892,8606],{"class":89},[73,8894,1382],{"class":82},[73,8896,8897,8899,8901],{"class":75,"line":1209},[73,8898,8613],{"class":82},[73,8900,8616],{"class":89},[73,8902,5035],{"class":82},[73,8904,8905,8907,8910,8912,8914,8916,8918,8920,8923,8925],{"class":75,"line":1215},[73,8906,5046],{"class":89},[73,8908,8909],{"class":79}," events",[73,8911,90],{"class":89},[73,8913,8630],{"class":82},[73,8915,8633],{"class":284},[73,8917,496],{"class":82},[73,8919,8638],{"class":992},[73,8921,8922],{"class":79},"\\n\\n",[73,8924,8638],{"class":992},[73,8926,3111],{"class":82},[73,8928,8929,8931,8933,8936,8938],{"class":75,"line":1221},[73,8930,8613],{"class":82},[73,8932,989],{"class":89},[73,8934,8935],{"class":82}," events.",[73,8937,8657],{"class":284},[73,8939,8053],{"class":82},[73,8941,8942,8944,8946,8948,8951,8953],{"class":75,"line":1227},[73,8943,5086],{"class":89},[73,8945,2224],{"class":82},[73,8947,423],{"class":89},[73,8949,8950],{"class":79}," event",[73,8952,5096],{"class":89},[73,8954,8955],{"class":82}," events) {\n",[73,8957,8958,8960,8962,8964],{"class":75,"line":1233},[73,8959,5438],{"class":89},[73,8961,1473],{"class":79},[73,8963,90],{"class":89},[73,8965,8966],{"class":82}," event\n",[73,8968,8969,8972,8974,8976,8978,8980,8982],{"class":75,"line":1899},[73,8970,8971],{"class":82},"                .",[73,8973,8633],{"class":284},[73,8975,496],{"class":82},[73,8977,8638],{"class":992},[73,8979,8641],{"class":79},[73,8981,8638],{"class":992},[73,8983,1545],{"class":82},[73,8985,8986,8988,8991,8993,8996,8999,9002,9005,9007,9010],{"class":75,"line":1913},[73,8987,8971],{"class":82},[73,8989,8990],{"class":284},"filter",[73,8992,496],{"class":82},[73,8994,8995],{"class":686},"l",[73,8997,8998],{"class":89}," =>",[73,9000,9001],{"class":82}," l.",[73,9003,9004],{"class":284},"startsWith",[73,9006,496],{"class":82},[73,9008,9009],{"class":992},"'data:'",[73,9011,9012],{"class":82},"))\n",[73,9014,9015,9017,9020,9022,9024,9026,9028,9030,9032,9035,9037,9039],{"class":75,"line":1918},[73,9016,8971],{"class":82},[73,9018,9019],{"class":284},"map",[73,9021,496],{"class":82},[73,9023,8995],{"class":686},[73,9025,8998],{"class":89},[73,9027,9001],{"class":82},[73,9029,718],{"class":284},[73,9031,496],{"class":82},[73,9033,9034],{"class":79},"5",[73,9036,735],{"class":82},[73,9038,8685],{"class":284},[73,9040,8530],{"class":82},[73,9042,9043,9045,9048,9050,9052,9054,9056],{"class":75,"line":1927},[73,9044,8971],{"class":82},[73,9046,9047],{"class":284},"join",[73,9049,496],{"class":82},[73,9051,8638],{"class":992},[73,9053,8641],{"class":79},[73,9055,8638],{"class":992},[73,9057,3111],{"class":82},[73,9059,9060,9063],{"class":75,"line":1935},[73,9061,9062],{"class":89},"            yield",[73,9064,9065],{"class":82}," data;\n",[73,9067,9068],{"class":75,"line":1943},[73,9069,4857],{"class":82},[73,9071,9072],{"class":75,"line":1952},[73,9073,2984],{"class":82},[73,9075,9076],{"class":75,"line":1966},[73,9077,746],{"class":82},[10,9079,9080],{},"CSV流式解析，CSV的结构如下：",[64,9082,9086],{"className":9083,"code":9084,"language":9085,"meta":69,"style":69},"language-csv shiki shiki-themes github-light github-dark","name,age,city\nAlice,30,Beijing\nBob,25,Shanghai\nCharlie,35,Guangzhou\n...\n","csv",[26,9087,9088,9093,9098,9103,9108],{"__ignoreMap":69},[73,9089,9090],{"class":75,"line":76},[73,9091,9092],{},"name,age,city\n",[73,9094,9095],{"class":75,"line":102},[73,9096,9097],{},"Alice,30,Beijing\n",[73,9099,9100],{"class":75,"line":120},[73,9101,9102],{},"Bob,25,Shanghai\n",[73,9104,9105],{"class":75,"line":139},[73,9106,9107],{},"Charlie,35,Guangzhou\n",[73,9109,9110],{"class":75,"line":159},[73,9111,207],{},[10,9113,9114,9115,9118],{},"每条记录以\\n或者\\r\\n结束，列分隔用,分隔，不像json有嵌套结构，不需要等整个文档解析完。无全局头，第一行是列名，之后每行独立。因此我们需要从ReadableStream或者文件读取一块数据，用TextDecorder按UTF-8解码，按照\\n切分，最后一行可能不完整，留在缓冲区。把每行按 ",[26,9116,9117],{},","," 切分成字段，每行独立处理，不需要等下一行。",[64,9120,9122],{"className":1157,"code":9121,"language":1159,"meta":69,"style":69},"async function* parseCSV(stream) {\n    const reader = stream\n        .pipeThrough(new TextDecoderStream())\n        .getReader();\n    let buffer = '';\n    let headers = null;\n\n    while (true) {\n        const { done, value } = await reader.read();\n        if (done) break;\n        buffer += value;\n        const lines = buffer.split('\\n');\n        buffer = lines.pop();\n\n        for (const line of lines) {\n            const cells = line.split(',');\n            if (!headers) {\n                headers = cells;\n            } else {\n                yield Object.fromEntries(\n                    headers.map((h, i) => [h, cells[i]])\n                );\n            }\n        }\n    }\n}\n\n\u002F\u002F 使用\nconst response = await fetch('\u002Fdata.csv');\nfor await (const row of parseCSV(response.body)) {\n    console.log(row);  \u002F\u002F { name: 'Alice', age: '30', city: 'Beijing' }\n}\n",[26,9123,9124,9139,9149,9163,9171,9183,9196,9200,9210,9234,9244,9252,9274,9286,9290,9304,9325,9337,9347,9355,9367,9390,9394,9398,9402,9406,9410,9414,9419,9438,9457,9469],{"__ignoreMap":69},[73,9125,9126,9128,9130,9133,9135,9137],{"class":75,"line":76},[73,9127,1522],{"class":89},[73,9129,8493],{"class":89},[73,9131,9132],{"class":284}," parseCSV",[73,9134,496],{"class":82},[73,9136,8256],{"class":686},[73,9138,696],{"class":82},[73,9140,9141,9143,9145,9147],{"class":75,"line":102},[73,9142,2076],{"class":89},[73,9144,8509],{"class":79},[73,9146,90],{"class":89},[73,9148,8514],{"class":82},[73,9150,9151,9153,9155,9157,9159,9161],{"class":75,"line":120},[73,9152,8519],{"class":82},[73,9154,7890],{"class":284},[73,9156,496],{"class":82},[73,9158,389],{"class":89},[73,9160,7897],{"class":284},[73,9162,8530],{"class":82},[73,9164,9165,9167,9169],{"class":75,"line":139},[73,9166,8519],{"class":82},[73,9168,8537],{"class":284},[73,9170,8053],{"class":82},[73,9172,9173,9175,9177,9179,9181],{"class":75,"line":159},[73,9174,6777],{"class":89},[73,9176,8546],{"class":82},[73,9178,989],{"class":89},[73,9180,8551],{"class":992},[73,9182,1382],{"class":82},[73,9184,9185,9187,9190,9192,9194],{"class":75,"line":178},[73,9186,6777],{"class":89},[73,9188,9189],{"class":82}," headers ",[73,9191,989],{"class":89},[73,9193,344],{"class":79},[73,9195,1382],{"class":82},[73,9197,9198],{"class":75,"line":204},[73,9199,437],{"emptyLinePlaceholder":436},[73,9201,9202,9204,9206,9208],{"class":75,"line":1198},[73,9203,6793],{"class":89},[73,9205,2224],{"class":82},[73,9207,1439],{"class":79},[73,9209,696],{"class":82},[73,9211,9212,9214,9216,9218,9220,9222,9224,9226,9228,9230,9232],{"class":75,"line":1203},[73,9213,5046],{"class":89},[73,9215,8574],{"class":82},[73,9217,8577],{"class":79},[73,9219,726],{"class":82},[73,9221,687],{"class":79},[73,9223,8584],{"class":82},[73,9225,989],{"class":89},[73,9227,1478],{"class":89},[73,9229,8591],{"class":82},[73,9231,8594],{"class":284},[73,9233,8053],{"class":82},[73,9235,9236,9238,9240,9242],{"class":75,"line":1209},[73,9237,4748],{"class":89},[73,9239,8603],{"class":82},[73,9241,8606],{"class":89},[73,9243,1382],{"class":82},[73,9245,9246,9248,9250],{"class":75,"line":1215},[73,9247,8613],{"class":82},[73,9249,8616],{"class":89},[73,9251,5035],{"class":82},[73,9253,9254,9256,9258,9260,9262,9264,9266,9268,9270,9272],{"class":75,"line":1221},[73,9255,5046],{"class":89},[73,9257,8625],{"class":79},[73,9259,90],{"class":89},[73,9261,8630],{"class":82},[73,9263,8633],{"class":284},[73,9265,496],{"class":82},[73,9267,8638],{"class":992},[73,9269,8641],{"class":79},[73,9271,8638],{"class":992},[73,9273,3111],{"class":82},[73,9275,9276,9278,9280,9282,9284],{"class":75,"line":1227},[73,9277,8613],{"class":82},[73,9279,989],{"class":89},[73,9281,8654],{"class":82},[73,9283,8657],{"class":284},[73,9285,8053],{"class":82},[73,9287,9288],{"class":75,"line":1233},[73,9289,437],{"emptyLinePlaceholder":436},[73,9291,9292,9294,9296,9298,9300,9302],{"class":75,"line":1899},[73,9293,5086],{"class":89},[73,9295,2224],{"class":82},[73,9297,423],{"class":89},[73,9299,8670],{"class":79},[73,9301,5096],{"class":89},[73,9303,8675],{"class":82},[73,9305,9306,9308,9311,9313,9316,9318,9320,9323],{"class":75,"line":1913},[73,9307,5438],{"class":89},[73,9309,9310],{"class":79}," cells",[73,9312,90],{"class":89},[73,9314,9315],{"class":82}," line.",[73,9317,8633],{"class":284},[73,9319,496],{"class":82},[73,9321,9322],{"class":992},"','",[73,9324,3111],{"class":82},[73,9326,9327,9329,9331,9334],{"class":75,"line":1918},[73,9328,5887],{"class":89},[73,9330,2224],{"class":82},[73,9332,9333],{"class":89},"!",[73,9335,9336],{"class":82},"headers) {\n",[73,9338,9339,9342,9344],{"class":75,"line":1927},[73,9340,9341],{"class":82},"                headers ",[73,9343,989],{"class":89},[73,9345,9346],{"class":82}," cells;\n",[73,9348,9349,9351,9353],{"class":75,"line":1935},[73,9350,4826],{"class":82},[73,9352,5616],{"class":89},[73,9354,1369],{"class":82},[73,9356,9357,9360,9362,9365],{"class":75,"line":1943},[73,9358,9359],{"class":89},"                yield",[73,9361,3701],{"class":82},[73,9363,9364],{"class":284},"fromEntries",[73,9366,3907],{"class":82},[73,9368,9369,9372,9374,9376,9379,9381,9383,9385,9387],{"class":75,"line":1952},[73,9370,9371],{"class":82},"                    headers.",[73,9373,9019],{"class":284},[73,9375,4028],{"class":82},[73,9377,9378],{"class":686},"h",[73,9380,726],{"class":82},[73,9382,7619],{"class":686},[73,9384,3927],{"class":82},[73,9386,1766],{"class":89},[73,9388,9389],{"class":82}," [h, cells[i]])\n",[73,9391,9392],{"class":75,"line":1966},[73,9393,4821],{"class":82},[73,9395,9396],{"class":75,"line":2987},[73,9397,4851],{"class":82},[73,9399,9400],{"class":75,"line":2992},[73,9401,4857],{"class":82},[73,9403,9404],{"class":75,"line":2998},[73,9405,2984],{"class":82},[73,9407,9408],{"class":75,"line":3013},[73,9409,746],{"class":82},[73,9411,9412],{"class":75,"line":3018},[73,9413,437],{"emptyLinePlaceholder":436},[73,9415,9416],{"class":75,"line":3023},[73,9417,9418],{"class":291},"\u002F\u002F 使用\n",[73,9420,9421,9423,9425,9427,9429,9431,9433,9436],{"class":75,"line":3029},[73,9422,423],{"class":89},[73,9424,7751],{"class":79},[73,9426,90],{"class":89},[73,9428,1478],{"class":89},[73,9430,1559],{"class":284},[73,9432,496],{"class":82},[73,9434,9435],{"class":992},"'\u002Fdata.csv'",[73,9437,3111],{"class":82},[73,9439,9440,9442,9444,9446,9448,9451,9453,9455],{"class":75,"line":3037},[73,9441,2221],{"class":89},[73,9443,1478],{"class":89},[73,9445,2224],{"class":82},[73,9447,423],{"class":89},[73,9449,9450],{"class":79}," row",[73,9452,5096],{"class":89},[73,9454,9132],{"class":284},[73,9456,8756],{"class":82},[73,9458,9459,9461,9463,9466],{"class":75,"line":3042},[73,9460,2089],{"class":82},[73,9462,758],{"class":284},[73,9464,9465],{"class":82},"(row);  ",[73,9467,9468],{"class":291},"\u002F\u002F { name: 'Alice', age: '30', city: 'Beijing' }\n",[73,9470,9471],{"class":75,"line":3047},[73,9472,746],{"class":82},[10,9474,9475],{},"SSR流式HTML渲染，如果这个放在web worker之后就需要使用postMessage把HTML片段传回主线程，由主线程来插入DOM，这是因为Worker不能操作DOM，因为DOM不是线程安全的，多线程操作DOM会导致状态不一致，worker是独立环境，也没有DOM api",[10,9477,9478],{},"这个有点像之前微软设计STA模型的时候同样的根本性考虑，为了保护一个非线程安全的共享资源，比如限制它只能被特定的线程访问。DOM和COM组件都不是线程安全的。",[10,9480,9481],{},"它们的解决方案也很相似，两者都采用了代理proxy+消息传递的模式来安全地转发调用，COM STA中，来自其他线程的调用视图访问STA对象时候，COM运行时不会直接调用，而是通过一个代理将调用编组成一条窗口消息，投递到对象所属STA线程的消息队列里，对象线程通过GetMessage\u002FDispatchMessage取出消息并处理这个消息。",[10,9483,9484],{},"Worker也一样，他必须通过postMessage将数据序列化后发送给主线程，主线程收到了消息之后再自己的执行环境下执行真正的DOM操作。",[64,9486,9488],{"className":1157,"code":9487,"language":1159,"meta":69,"style":69},"const response = await fetch('\u002Fpage');\n\nconst stream = response.body\n    .pipeThrough(new TextDecoderStream())\n    .pipeThrough(new TransformStream({\n        transform(chunk, controller) {\n            \u002F\u002F 在 HTML 到达时逐块插入 DOM\n            document.getElementById('app').insertAdjacentHTML('beforeend', chunk);\n            controller.enqueue(chunk);\n        }\n    }));\n\nawait new Response(stream).text();\n",[26,9489,9490,9509,9513,9523,9537,9551,9565,9570,9596,9604,9608,9612,9616],{"__ignoreMap":69},[73,9491,9492,9494,9496,9498,9500,9502,9504,9507],{"class":75,"line":76},[73,9493,423],{"class":89},[73,9495,7751],{"class":79},[73,9497,90],{"class":89},[73,9499,1478],{"class":89},[73,9501,1559],{"class":284},[73,9503,496],{"class":82},[73,9505,9506],{"class":992},"'\u002Fpage'",[73,9508,3111],{"class":82},[73,9510,9511],{"class":75,"line":102},[73,9512,437],{"emptyLinePlaceholder":436},[73,9514,9515,9517,9519,9521],{"class":75,"line":120},[73,9516,423],{"class":89},[73,9518,7877],{"class":79},[73,9520,90],{"class":89},[73,9522,7882],{"class":82},[73,9524,9525,9527,9529,9531,9533,9535],{"class":75,"line":139},[73,9526,7887],{"class":82},[73,9528,7890],{"class":284},[73,9530,496],{"class":82},[73,9532,389],{"class":89},[73,9534,7897],{"class":284},[73,9536,8530],{"class":82},[73,9538,9539,9541,9543,9545,9547,9549],{"class":75,"line":159},[73,9540,7887],{"class":82},[73,9542,7890],{"class":284},[73,9544,496],{"class":82},[73,9546,389],{"class":89},[73,9548,7915],{"class":284},[73,9550,7781],{"class":82},[73,9552,9553,9555,9557,9559,9561,9563],{"class":75,"line":178},[73,9554,7926],{"class":284},[73,9556,496],{"class":82},[73,9558,7791],{"class":686},[73,9560,726],{"class":82},[73,9562,7935],{"class":686},[73,9564,696],{"class":82},[73,9566,9567],{"class":75,"line":204},[73,9568,9569],{"class":291},"            \u002F\u002F 在 HTML 到达时逐块插入 DOM\n",[73,9571,9572,9575,9578,9580,9583,9585,9588,9590,9593],{"class":75,"line":1198},[73,9573,9574],{"class":82},"            document.",[73,9576,9577],{"class":284},"getElementById",[73,9579,496],{"class":82},[73,9581,9582],{"class":992},"'app'",[73,9584,735],{"class":82},[73,9586,9587],{"class":284},"insertAdjacentHTML",[73,9589,496],{"class":82},[73,9591,9592],{"class":992},"'beforeend'",[73,9594,9595],{"class":82},", chunk);\n",[73,9597,9598,9600,9602],{"class":75,"line":1203},[73,9599,7942],{"class":82},[73,9601,7945],{"class":284},[73,9603,7994],{"class":82},[73,9605,9606],{"class":75,"line":1209},[73,9607,4857],{"class":82},[73,9609,9610],{"class":75,"line":1215},[73,9611,7963],{"class":82},[73,9613,9614],{"class":75,"line":1221},[73,9615,437],{"emptyLinePlaceholder":436},[73,9617,9618,9620,9622,9624,9626,9628],{"class":75,"line":1227},[73,9619,929],{"class":89},[73,9621,281],{"class":89},[73,9623,8203],{"class":284},[73,9625,8206],{"class":82},[73,9627,2008],{"class":284},[73,9629,8053],{"class":82},[10,9631,9632],{},"流式Markdown:",[64,9634,9636],{"className":1157,"code":9635,"language":1159,"meta":69,"style":69},"const response = await fetch('\u002Farticle.md');\nconst stream = response.body\n    .pipeThrough(new TextDecoderStream())\n    .pipeThrough(new TransformStream({\n        transform(chunk, controller) {\n            const html = markdownToHTML(chunk);\n            document.getElementById('content').insertAdjacentHTML('beforeend', html);\n            controller.enqueue(chunk);\n        }\n    }));\n",[26,9637,9638,9657,9667,9681,9695,9709,9723,9745,9753,9757],{"__ignoreMap":69},[73,9639,9640,9642,9644,9646,9648,9650,9652,9655],{"class":75,"line":76},[73,9641,423],{"class":89},[73,9643,7751],{"class":79},[73,9645,90],{"class":89},[73,9647,1478],{"class":89},[73,9649,1559],{"class":284},[73,9651,496],{"class":82},[73,9653,9654],{"class":992},"'\u002Farticle.md'",[73,9656,3111],{"class":82},[73,9658,9659,9661,9663,9665],{"class":75,"line":102},[73,9660,423],{"class":89},[73,9662,7877],{"class":79},[73,9664,90],{"class":89},[73,9666,7882],{"class":82},[73,9668,9669,9671,9673,9675,9677,9679],{"class":75,"line":120},[73,9670,7887],{"class":82},[73,9672,7890],{"class":284},[73,9674,496],{"class":82},[73,9676,389],{"class":89},[73,9678,7897],{"class":284},[73,9680,8530],{"class":82},[73,9682,9683,9685,9687,9689,9691,9693],{"class":75,"line":139},[73,9684,7887],{"class":82},[73,9686,7890],{"class":284},[73,9688,496],{"class":82},[73,9690,389],{"class":89},[73,9692,7915],{"class":284},[73,9694,7781],{"class":82},[73,9696,9697,9699,9701,9703,9705,9707],{"class":75,"line":159},[73,9698,7926],{"class":284},[73,9700,496],{"class":82},[73,9702,7791],{"class":686},[73,9704,726],{"class":82},[73,9706,7935],{"class":686},[73,9708,696],{"class":82},[73,9710,9711,9713,9716,9718,9721],{"class":75,"line":178},[73,9712,5438],{"class":89},[73,9714,9715],{"class":79}," html",[73,9717,90],{"class":89},[73,9719,9720],{"class":284}," markdownToHTML",[73,9722,7994],{"class":82},[73,9724,9725,9727,9729,9731,9734,9736,9738,9740,9742],{"class":75,"line":204},[73,9726,9574],{"class":82},[73,9728,9577],{"class":284},[73,9730,496],{"class":82},[73,9732,9733],{"class":992},"'content'",[73,9735,735],{"class":82},[73,9737,9587],{"class":284},[73,9739,496],{"class":82},[73,9741,9592],{"class":992},[73,9743,9744],{"class":82},", html);\n",[73,9746,9747,9749,9751],{"class":75,"line":1198},[73,9748,7942],{"class":82},[73,9750,7945],{"class":284},[73,9752,7994],{"class":82},[73,9754,9755],{"class":75,"line":1203},[73,9756,4857],{"class":82},[73,9758,9759],{"class":75,"line":1209},[73,9760,7963],{"class":82},[10,9762,9763],{},"AI 流式输出",[64,9765,9767],{"className":1157,"code":9766,"language":1159,"meta":69,"style":69},"const response = await fetch('\u002Fapi\u002Fchat', {\n    method: 'POST',\n    body: JSON.stringify({ prompt: 'Hello' })\n});\n\nconst reader = response.body\n    .pipeThrough(new TextDecoderStream())\n    .getReader();\n\nwhile (true) {\n    const { done, value } = await reader.read();\n    if (done) break;\n    \u002F\u002F 逐字输出\n    document.getElementById('output').textContent += value;\n}\n",[26,9768,9769,9789,9799,9820,9824,9828,9838,9852,9860,9864,9875,9899,9909,9914,9933],{"__ignoreMap":69},[73,9770,9771,9773,9775,9777,9779,9781,9783,9786],{"class":75,"line":76},[73,9772,423],{"class":89},[73,9774,7751],{"class":79},[73,9776,90],{"class":89},[73,9778,1478],{"class":89},[73,9780,1559],{"class":284},[73,9782,496],{"class":82},[73,9784,9785],{"class":992},"'\u002Fapi\u002Fchat'",[73,9787,9788],{"class":82},", {\n",[73,9790,9791,9794,9797],{"class":75,"line":102},[73,9792,9793],{"class":82},"    method: ",[73,9795,9796],{"class":992},"'POST'",[73,9798,3073],{"class":82},[73,9800,9801,9804,9807,9809,9812,9815,9817],{"class":75,"line":120},[73,9802,9803],{"class":82},"    body: ",[73,9805,9806],{"class":79},"JSON",[73,9808,484],{"class":82},[73,9810,9811],{"class":284},"stringify",[73,9813,9814],{"class":82},"({ prompt: ",[73,9816,3383],{"class":992},[73,9818,9819],{"class":82}," })\n",[73,9821,9822],{"class":75,"line":139},[73,9823,7826],{"class":82},[73,9825,9826],{"class":75,"line":159},[73,9827,437],{"emptyLinePlaceholder":436},[73,9829,9830,9832,9834,9836],{"class":75,"line":178},[73,9831,423],{"class":89},[73,9833,8509],{"class":79},[73,9835,90],{"class":89},[73,9837,7882],{"class":82},[73,9839,9840,9842,9844,9846,9848,9850],{"class":75,"line":204},[73,9841,7887],{"class":82},[73,9843,7890],{"class":284},[73,9845,496],{"class":82},[73,9847,389],{"class":89},[73,9849,7897],{"class":284},[73,9851,8530],{"class":82},[73,9853,9854,9856,9858],{"class":75,"line":1198},[73,9855,7887],{"class":82},[73,9857,8537],{"class":284},[73,9859,8053],{"class":82},[73,9861,9862],{"class":75,"line":1203},[73,9863,437],{"emptyLinePlaceholder":436},[73,9865,9866,9869,9871,9873],{"class":75,"line":1209},[73,9867,9868],{"class":89},"while",[73,9870,2224],{"class":82},[73,9872,1439],{"class":79},[73,9874,696],{"class":82},[73,9876,9877,9879,9881,9883,9885,9887,9889,9891,9893,9895,9897],{"class":75,"line":1215},[73,9878,2076],{"class":89},[73,9880,8574],{"class":82},[73,9882,8577],{"class":79},[73,9884,726],{"class":82},[73,9886,687],{"class":79},[73,9888,8584],{"class":82},[73,9890,989],{"class":89},[73,9892,1478],{"class":89},[73,9894,8591],{"class":82},[73,9896,8594],{"class":284},[73,9898,8053],{"class":82},[73,9900,9901,9903,9905,9907],{"class":75,"line":1221},[73,9902,2945],{"class":89},[73,9904,8603],{"class":82},[73,9906,8606],{"class":89},[73,9908,1382],{"class":82},[73,9910,9911],{"class":75,"line":1227},[73,9912,9913],{"class":291},"    \u002F\u002F 逐字输出\n",[73,9915,9916,9919,9921,9923,9926,9929,9931],{"class":75,"line":1233},[73,9917,9918],{"class":82},"    document.",[73,9920,9577],{"class":284},[73,9922,496],{"class":82},[73,9924,9925],{"class":992},"'output'",[73,9927,9928],{"class":82},").textContent ",[73,9930,8616],{"class":89},[73,9932,5035],{"class":82},[73,9934,9935],{"class":75,"line":1899},[73,9936,746],{"class":82},[8124,9938,9939],{"id":9939},"音视频处理",[10,9941,9942],{},"音频流式",[64,9944,9946],{"className":1157,"code":9945,"language":1159,"meta":69,"style":69},"const response = await fetch('\u002Faudio.mp3');\nconst audioContext = new AudioContext();\nconst source = audioContext.createMediaStreamSource(\n    new MediaStream([\u002F* ... *\u002F])\n);\n",[26,9947,9948,9967,9983,10000,10013],{"__ignoreMap":69},[73,9949,9950,9952,9954,9956,9958,9960,9962,9965],{"class":75,"line":76},[73,9951,423],{"class":89},[73,9953,7751],{"class":79},[73,9955,90],{"class":89},[73,9957,1478],{"class":89},[73,9959,1559],{"class":284},[73,9961,496],{"class":82},[73,9963,9964],{"class":992},"'\u002Faudio.mp3'",[73,9966,3111],{"class":82},[73,9968,9969,9971,9974,9976,9978,9981],{"class":75,"line":102},[73,9970,423],{"class":89},[73,9972,9973],{"class":79}," audioContext",[73,9975,90],{"class":89},[73,9977,281],{"class":89},[73,9979,9980],{"class":284}," AudioContext",[73,9982,8053],{"class":82},[73,9984,9985,9987,9990,9992,9995,9998],{"class":75,"line":120},[73,9986,423],{"class":89},[73,9988,9989],{"class":79}," source",[73,9991,90],{"class":89},[73,9993,9994],{"class":82}," audioContext.",[73,9996,9997],{"class":284},"createMediaStreamSource",[73,9999,3907],{"class":82},[73,10001,10002,10004,10007,10009,10011],{"class":75,"line":139},[73,10003,2595],{"class":89},[73,10005,10006],{"class":284}," MediaStream",[73,10008,8243],{"class":82},[73,10010,8092],{"class":291},[73,10012,8249],{"class":82},[73,10014,10015],{"class":75,"line":159},[73,10016,3111],{"class":82},[10,10018,10019],{},"视频流式录制：",[64,10021,10023],{"className":1157,"code":10022,"language":1159,"meta":69,"style":69},"const stream = await navigator.mediaDevices.getUserMedia({ video: true });\nconst recorder = new MediaRecorder(stream);\n\nconst writable = new WritableStream({\n    write(chunk) {\n        \u002F\u002F 把录制的数据块上传或保存\n    }\n});\n\nrecorder.ondataavailable = (e) => {\n    writable.getWriter().write(e.data);\n};\n",[26,10024,10025,10049,10066,10070,10084,10094,10099,10103,10107,10111,10131,10146],{"__ignoreMap":69},[73,10026,10027,10029,10031,10033,10035,10038,10041,10044,10046],{"class":75,"line":76},[73,10028,423],{"class":89},[73,10030,7877],{"class":79},[73,10032,90],{"class":89},[73,10034,1478],{"class":89},[73,10036,10037],{"class":82}," navigator.mediaDevices.",[73,10039,10040],{"class":284},"getUserMedia",[73,10042,10043],{"class":82},"({ video: ",[73,10045,1439],{"class":79},[73,10047,10048],{"class":82}," });\n",[73,10050,10051,10053,10056,10058,10060,10063],{"class":75,"line":102},[73,10052,423],{"class":89},[73,10054,10055],{"class":79}," recorder",[73,10057,90],{"class":89},[73,10059,281],{"class":89},[73,10061,10062],{"class":284}," MediaRecorder",[73,10064,10065],{"class":82},"(stream);\n",[73,10067,10068],{"class":75,"line":120},[73,10069,437],{"emptyLinePlaceholder":436},[73,10071,10072,10074,10076,10078,10080,10082],{"class":75,"line":139},[73,10073,423],{"class":89},[73,10075,7771],{"class":79},[73,10077,90],{"class":89},[73,10079,281],{"class":89},[73,10081,7778],{"class":284},[73,10083,7781],{"class":82},[73,10085,10086,10088,10090,10092],{"class":75,"line":159},[73,10087,7786],{"class":284},[73,10089,496],{"class":82},[73,10091,7791],{"class":686},[73,10093,696],{"class":82},[73,10095,10096],{"class":75,"line":178},[73,10097,10098],{"class":291},"        \u002F\u002F 把录制的数据块上传或保存\n",[73,10100,10101],{"class":75,"line":204},[73,10102,2984],{"class":82},[73,10104,10105],{"class":75,"line":1198},[73,10106,7826],{"class":82},[73,10108,10109],{"class":75,"line":1203},[73,10110,437],{"emptyLinePlaceholder":436},[73,10112,10113,10116,10119,10121,10123,10125,10127,10129],{"class":75,"line":1209},[73,10114,10115],{"class":82},"recorder.",[73,10117,10118],{"class":284},"ondataavailable",[73,10120,90],{"class":89},[73,10122,2224],{"class":82},[73,10124,5591],{"class":686},[73,10126,3927],{"class":82},[73,10128,1766],{"class":89},[73,10130,1369],{"class":82},[73,10132,10133,10136,10139,10141,10143],{"class":75,"line":1215},[73,10134,10135],{"class":82},"    writable.",[73,10137,10138],{"class":284},"getWriter",[73,10140,1803],{"class":82},[73,10142,8081],{"class":284},[73,10144,10145],{"class":82},"(e.data);\n",[73,10147,10148],{"class":75,"line":1221},[73,10149,10150],{"class":82},"};\n",[10,10152,10153],{},"vueuse提供了两个处理web worker的组合式函数：useWebWorker和useWebWorkerFn，分别对应托管现成Worker脚本和直接包装函数体两种场景。",[64,10155,10157],{"className":1157,"code":10156,"language":1159,"meta":69,"style":69},"import { useWebWorkerFn } from '@vueuse\u002Fcore'\n\nconst { workerFn } = useWebWorkerFn((numbers) => {\n  \u002F\u002F 这里是耗时的重计算\n  return numbers.sort((a, b) => a - b)\n})\n\n\u002F\u002F 调用 workerFn，返回 Promise\nconst sorted = await workerFn(hugeArray)\n\n",[26,10158,10159,10171,10175,10202,10207,10238,10242,10246,10251],{"__ignoreMap":69},[73,10160,10161,10163,10166,10168],{"class":75,"line":76},[73,10162,814],{"class":89},[73,10164,10165],{"class":82}," { useWebWorkerFn } ",[73,10167,7294],{"class":89},[73,10169,10170],{"class":992}," '@vueuse\u002Fcore'\n",[73,10172,10173],{"class":75,"line":102},[73,10174,437],{"emptyLinePlaceholder":436},[73,10176,10177,10179,10181,10184,10186,10188,10191,10193,10196,10198,10200],{"class":75,"line":120},[73,10178,423],{"class":89},[73,10180,8574],{"class":82},[73,10182,10183],{"class":79},"workerFn",[73,10185,8584],{"class":82},[73,10187,989],{"class":89},[73,10189,10190],{"class":284}," useWebWorkerFn",[73,10192,4028],{"class":82},[73,10194,10195],{"class":686},"numbers",[73,10197,3927],{"class":82},[73,10199,1766],{"class":89},[73,10201,1369],{"class":82},[73,10203,10204],{"class":75,"line":139},[73,10205,10206],{"class":291},"  \u002F\u002F 这里是耗时的重计算\n",[73,10208,10209,10211,10214,10217,10219,10222,10224,10227,10229,10231,10233,10235],{"class":75,"line":159},[73,10210,701],{"class":89},[73,10212,10213],{"class":82}," numbers.",[73,10215,10216],{"class":284},"sort",[73,10218,4028],{"class":82},[73,10220,10221],{"class":686},"a",[73,10223,726],{"class":82},[73,10225,10226],{"class":686},"b",[73,10228,3927],{"class":82},[73,10230,1766],{"class":89},[73,10232,2181],{"class":82},[73,10234,729],{"class":89},[73,10236,10237],{"class":82}," b)\n",[73,10239,10240],{"class":75,"line":178},[73,10241,3215],{"class":82},[73,10243,10244],{"class":75,"line":204},[73,10245,437],{"emptyLinePlaceholder":436},[73,10247,10248],{"class":75,"line":1198},[73,10249,10250],{"class":291},"\u002F\u002F 调用 workerFn，返回 Promise\n",[73,10252,10253,10255,10258,10260,10262,10265],{"class":75,"line":1203},[73,10254,423],{"class":89},[73,10256,10257],{"class":79}," sorted",[73,10259,90],{"class":89},[73,10261,1478],{"class":89},[73,10263,10264],{"class":284}," workerFn",[73,10266,10267],{"class":82},"(hugeArray)\n",[14,10269,2344],{"id":2344},[10,10271,10272,10273,10276],{},"闭包主要是通过上下文对象和作用域链实现的，",[21,10274,10275],{},"内部函数引用了外部函数的变量的时候","，v8会把这些变量从栈上搬到堆上的上下文对象中，这样内部的函数可以通过作用域链来访问它们。正常情况下函数执行的时候局部变量会分配在调用栈上，函数一旦返回，变量就会随着栈帧一起销毁。但是闭包会打破这个规则，v8发现一个内部函数引用了外部函数变量，那么就让这个变量在外部函数返回后仍需存活，v8会把这些被引用的变量以及可能其他被引用的变量从栈提升到堆上，封装成一个上下文对象。",[10,10278,10279,10280,10283],{},"可以把上下文理解为一个特殊的环境记录，用来保存那些需要活过外部函数生命周期的变量。每个函数对象内部都有一个隐藏的 ",[26,10281,10282],{},"[[Environment]]","槽，称为Scope内部属性，当函数被创建的时候，这个属性会指向它定义时候所处的词法环境，也就是外层context对象。闭包执行并需要访问外部的变量，v8就会沿着这条链去找。",[10,10285,10286,10287,10290,10291,10294],{},"v8不会盲目保存所有变量，而是依靠惰性解析，v8首次解析代码的时候遇到",[21,10288,10289],{},"函数声明","会跳过其内部代码，",[21,10292,10293],{},"只生成顶层的AST和字节码","，然后进行静态分析，只把内部函数实际引用的变量提升到上下文对象，而不是外部函数所有的局部变量，如果某个变量没有被闭包引用，他依然留在栈上，执行完销毁。",[10,10296,10297],{},"结合之前的js核心运行机制可以推断出：",[10,10299,10300,10301,10304,10305,10308],{},"词法环境和变量环境是抽象概念，v8层面，它们会被具象化为context对象，变量提升到context对象，",[21,10302,10303],{},"发生在外层函数执行的时候","，而不是内层函数查找的时候。V8 在编译外层函数时，就已经通过",[21,10306,10307],{},"静态分析","知道了 哪些变量会被内层函数引用，这些变量应该放在上下文的哪个槽位，所以外层函数一执行，V8 就直接在堆上创建 Context，把这些变量放进去。内层函数创建时，直接拿到这个 Context 的引用。",[10,10310,10311],{},"静态分析和逃逸分析",[10,10313,10314],{},"静态分析和逃逸分析是包含关系：",[64,10316,10319],{"className":10317,"code":10318,"language":2008},[2006],"编译优化\n  ├── 静态分析（Static Analysis）        ← 大类：编译期分析代码性质\n  │     ├── 逃逸分析（Escape Analysis）   ← 子类：分析变量是否“逃逸”\n  │     ├── 死代码消除\n  │     ├── 常量折叠\n  │     └── 内联分析\n  └── 动态分析（Dynamic Analysis）        ← 运行时分析\n",[26,10320,10318],{"__ignoreMap":69},[10,10322,10323],{},"静态分析是“在编译期分析代码性质”的总称，逃逸分析是其中专门用来判断“变量是否会逃出当前作用域”的技术。逃逸本意是指一个变量或者对象的生命周期是否会超出它被创建时的作用域，变量只在当前函数内使用，函数返回即销毁就叫做不逃逸，反之就是逃逸到堆。变量被传递到其他线程就叫做逃逸到其他线程。",[14,10325,10327],{"id":10326},"gc机制","GC机制",[10,10329,10330],{},"js的垃圾回收是引擎自动管理内存的机制，负责识别并回收不再被使用的内存，防止内存泄漏，v8的gc策略是分代回收+增量标记+并发清理的组合策略。",[10,10332,10333,10334,10337],{},"gc不关心这个变量叫什么，只关心这个对象还能不能访问到，从根对象出发，沿着引用链遍历，",[21,10335,10336],{},"能达到的对象就是可达的","，不能达到的就是不可达，会被回收掉。",[10,10339,10340],{},"根对象包括了window\u002FglobalThis，调用栈上的变量（当前执行函数的局部变量、参数）。闭包捕获的变量、DOM引用。",[10,10342,10343],{},"v8把堆内存分为了新生代和老生代，针对不同生命周期采用不同策略，新生代比较小可能就1-8MB，老生代比较大，可能几百MB甚至GB，新生代的生命周期比较短，老生代周期比较长。",[10,10345,10346,10347,1670,10350,232],{},"新生代使用Scavenge复制算法进行回收，老生代使用mark-sweep+mark-compact。把新生代分为两个半区：",[21,10348,10349],{},"From 空间",[21,10351,10352],{},"To 空间",[64,10354,10357],{"className":10355,"code":10356,"language":2008},[2006],"From 空间（使用中）    To 空间（空闲）\n┌─────────────┐      ┌─────────────┐\n│ 活对象       │      │             │\n│ 死对象       │      │             │\n└─────────────┘      └─────────────┘\n",[26,10358,10356],{"__ignoreMap":69},[10,10360,10361,10362,232],{},"从根出发，标记from空间中的活对象，把活对象复制到To空间，清空From空间，交换From和To的对象，如果对象经过多次 Scavenge 仍然存活，会被",[21,10363,10364],{},"晋升到老生代",[10,10366,10367,10368,10371,10372,10375,10380,10384],{},"分代思想是个很成熟的模型，就像CLR也是采用的三代模型的gc回收。第一代充当缓冲区，短期存活的对象有机会再0代回收后被快速清理，而不必升到2代，clr有大型对象堆LOH，任何大于85KB的对象会直接分配到LOH上，并被标记为2代， 它",[21,10369,10370],{},"只在完全 GC（第 2 代回收）时才会被清理","，且",[21,10373,10374],{},"默认不会被压缩",[10221,10376],{"href":10377,"rel":10378},"https:\u002F\u002Fgithub.com\u002Frambhawan\u002FComputer-Compiler-Lang\u002Fblob\u002F825822d3e676b2dc5a93d649ae8a4555cb606b93\u002FPro%20.Net%20Performance.pdf?_x_output_type_b6db407c4_=embedded_pdf#53#19",[10379],"nofollow",[10221,10381],{"href":10382,"rel":10383},"https:\u002F\u002Fm.yisu.com\u002Fzixun\u002F102253.html",[10379],"。这是因为移动大对象内存的代价很高，V8 没有专门的 LOH，所有对象都在新生代或老生代中处理。",[14,10386,10388],{"id":10387},"ts的类型","TS的类型",[10,10390,10391],{},"在ts之中，函数会被看做值，类型是函数类型(x: number) => string。方法是对象里的函数属性，类型也是函数类型。类方法是类原型上的函数，类型也是函数类型。因此可以推理得出：方法的泛型 = 函数类型的泛型，不是所有方法都有独立的类型系统。",[10,10393,10394,10395,10398],{},"泛型参数 ",[26,10396,10397],{},"\u003CT>","可以写在函数签名上，而不是写在类型别名\u002F接口\u002F类上。我们知道泛型有两种写法：",[64,10400,10402],{"className":1157,"code":10401,"language":1159,"meta":69,"style":69},"type Box\u003CT> = {\n    value: T;\n};\n\u002F\u002F   ^^^ T 是 Box 的类型参数\nconst b: Box\u003Cnumber> = { value: 1 };   \u002F\u002F 用类型时确定 T\n\nfunction identity\u003CT>(x: T): T {\n    \u002F\u002F           ^^^ T 是函数的类型参数\n    return x;\n}\nidentity\u003Cnumber>(1);   \u002F\u002F 调用函数时确定 T\n",[26,10403,10404,10421,10432,10436,10441,10471,10475,10502,10507,10514,10518],{"__ignoreMap":69},[73,10405,10406,10408,10411,10413,10415,10417,10419],{"class":75,"line":76},[73,10407,4183],{"class":89},[73,10409,10410],{"class":284}," Box",[73,10412,1089],{"class":82},[73,10414,4218],{"class":284},[73,10416,4566],{"class":82},[73,10418,989],{"class":89},[73,10420,1369],{"class":82},[73,10422,10423,10426,10428,10430],{"class":75,"line":102},[73,10424,10425],{"class":686},"    value",[73,10427,690],{"class":89},[73,10429,3893],{"class":284},[73,10431,1382],{"class":82},[73,10433,10434],{"class":75,"line":120},[73,10435,10150],{"class":82},[73,10437,10438],{"class":75,"line":139},[73,10439,10440],{"class":291},"\u002F\u002F   ^^^ T 是 Box 的类型参数\n",[73,10442,10443,10445,10447,10449,10451,10453,10456,10458,10460,10463,10465,10468],{"class":75,"line":159},[73,10444,423],{"class":89},[73,10446,2079],{"class":79},[73,10448,690],{"class":89},[73,10450,10410],{"class":284},[73,10452,1089],{"class":82},[73,10454,10455],{"class":79},"number",[73,10457,4566],{"class":82},[73,10459,989],{"class":89},[73,10461,10462],{"class":82}," { value: ",[73,10464,732],{"class":79},[73,10466,10467],{"class":82}," };   ",[73,10469,10470],{"class":291},"\u002F\u002F 用类型时确定 T\n",[73,10472,10473],{"class":75,"line":178},[73,10474,437],{"emptyLinePlaceholder":436},[73,10476,10477,10479,10482,10484,10486,10488,10490,10492,10494,10496,10498,10500],{"class":75,"line":204},[73,10478,356],{"class":89},[73,10480,10481],{"class":284}," identity",[73,10483,1089],{"class":82},[73,10485,4218],{"class":284},[73,10487,6133],{"class":82},[73,10489,2153],{"class":686},[73,10491,690],{"class":89},[73,10493,3893],{"class":284},[73,10495,4316],{"class":82},[73,10497,690],{"class":89},[73,10499,3893],{"class":284},[73,10501,1369],{"class":82},[73,10503,10504],{"class":75,"line":1198},[73,10505,10506],{"class":291},"    \u002F\u002F           ^^^ T 是函数的类型参数\n",[73,10508,10509,10511],{"class":75,"line":1203},[73,10510,3001],{"class":89},[73,10512,10513],{"class":82}," x;\n",[73,10515,10516],{"class":75,"line":1209},[73,10517,746],{"class":82},[73,10519,10520,10523,10525,10527,10529,10531,10534],{"class":75,"line":1215},[73,10521,10522],{"class":284},"identity",[73,10524,1089],{"class":82},[73,10526,10455],{"class":79},[73,10528,6133],{"class":82},[73,10530,732],{"class":79},[73,10532,10533],{"class":82},");   ",[73,10535,10536],{"class":291},"\u002F\u002F 调用函数时确定 T\n",[10,10538,10539],{},"两种泛型位置不同，分别叫做类型级泛型和调用级泛型。",[14,10541,10543],{"id":10542},"ts的基本模式","Ts的基本模式",[10,10545,10546],{},"ts有个非常常见的模式，使用interface来描述实例，一份interface描述构造函数并且包含静态方法，然后class同时满足。",[10,10548,10549],{},"我们使用的Array Function Promise全都是按照这个模式来编写的：",[64,10551,10553],{"className":1157,"code":10552,"language":1159,"meta":69,"style":69},"\u002F\u002F 1. 实例接口\ninterface User {\n    name: string;\n    age: number;\n    greet(): string;\n}\n\n\u002F\u002F 2. 构造函数接口（含静态方法）\ninterface UserConstructor {\n    new (name: string, age: number): User;   \u002F\u002F 构造签名\n    create(name: string, age: number): User; \u002F\u002F 静态方法\n    readonly MAX_AGE: number;                 \u002F\u002F 静态属性\n}\n\n\u002F\u002F 3. 类实现两者\nclass UserImpl implements User {\n    static MAX_AGE = 150;\n    \n    constructor(public name: string, public age: number) {}\n    \n    greet() {\n        return `Hi, I'm ${this.name}`;\n    }\n    \n    static create(name: string, age: number): User {\n        return new UserImpl(name, age);\n    }\n}\n\n\u002F\u002F 4. 用构造函数接口约束类本身\nconst UserClass: UserConstructor = UserImpl;   \u002F\u002F ✅\n",[26,10554,10555,10560,10569,10580,10591,10604,10608,10612,10617,10626,10659,10692,10709,10713,10717,10722,10736,10749,10754,10784,10788,10794,10811,10815,10819,10850,10861,10865,10869,10873,10878],{"__ignoreMap":69},[73,10556,10557],{"class":75,"line":76},[73,10558,10559],{"class":291},"\u002F\u002F 1. 实例接口\n",[73,10561,10562,10564,10567],{"class":75,"line":102},[73,10563,1363],{"class":89},[73,10565,10566],{"class":284}," User",[73,10568,1369],{"class":82},[73,10570,10571,10574,10576,10578],{"class":75,"line":120},[73,10572,10573],{"class":686},"    name",[73,10575,690],{"class":89},[73,10577,2608],{"class":79},[73,10579,1382],{"class":82},[73,10581,10582,10585,10587,10589],{"class":75,"line":139},[73,10583,10584],{"class":686},"    age",[73,10586,690],{"class":89},[73,10588,7352],{"class":79},[73,10590,1382],{"class":82},[73,10592,10593,10596,10598,10600,10602],{"class":75,"line":159},[73,10594,10595],{"class":284},"    greet",[73,10597,7579],{"class":82},[73,10599,690],{"class":89},[73,10601,2608],{"class":79},[73,10603,1382],{"class":82},[73,10605,10606],{"class":75,"line":178},[73,10607,746],{"class":82},[73,10609,10610],{"class":75,"line":204},[73,10611,437],{"emptyLinePlaceholder":436},[73,10613,10614],{"class":75,"line":1198},[73,10615,10616],{"class":291},"\u002F\u002F 2. 构造函数接口（含静态方法）\n",[73,10618,10619,10621,10624],{"class":75,"line":1203},[73,10620,1363],{"class":89},[73,10622,10623],{"class":284}," UserConstructor",[73,10625,1369],{"class":82},[73,10627,10628,10630,10632,10634,10636,10638,10640,10643,10645,10647,10649,10651,10653,10656],{"class":75,"line":1209},[73,10629,2595],{"class":89},[73,10631,2224],{"class":82},[73,10633,2489],{"class":686},[73,10635,690],{"class":89},[73,10637,2608],{"class":79},[73,10639,726],{"class":82},[73,10641,10642],{"class":686},"age",[73,10644,690],{"class":89},[73,10646,7352],{"class":79},[73,10648,4316],{"class":82},[73,10650,690],{"class":89},[73,10652,10566],{"class":284},[73,10654,10655],{"class":82},";   ",[73,10657,10658],{"class":291},"\u002F\u002F 构造签名\n",[73,10660,10661,10664,10666,10668,10670,10672,10674,10676,10678,10680,10682,10684,10686,10689],{"class":75,"line":1215},[73,10662,10663],{"class":284},"    create",[73,10665,496],{"class":82},[73,10667,2489],{"class":686},[73,10669,690],{"class":89},[73,10671,2608],{"class":79},[73,10673,726],{"class":82},[73,10675,10642],{"class":686},[73,10677,690],{"class":89},[73,10679,7352],{"class":79},[73,10681,4316],{"class":82},[73,10683,690],{"class":89},[73,10685,10566],{"class":284},[73,10687,10688],{"class":82},"; ",[73,10690,10691],{"class":291},"\u002F\u002F 静态方法\n",[73,10693,10694,10696,10699,10701,10703,10706],{"class":75,"line":1221},[73,10695,2644],{"class":89},[73,10697,10698],{"class":686}," MAX_AGE",[73,10700,690],{"class":89},[73,10702,7352],{"class":79},[73,10704,10705],{"class":82},";                 ",[73,10707,10708],{"class":291},"\u002F\u002F 静态属性\n",[73,10710,10711],{"class":75,"line":1227},[73,10712,746],{"class":82},[73,10714,10715],{"class":75,"line":1233},[73,10716,437],{"emptyLinePlaceholder":436},[73,10718,10719],{"class":75,"line":1899},[73,10720,10721],{"class":291},"\u002F\u002F 3. 类实现两者\n",[73,10723,10724,10726,10729,10732,10734],{"class":75,"line":1913},[73,10725,4556],{"class":89},[73,10727,10728],{"class":284}," UserImpl",[73,10730,10731],{"class":89}," implements",[73,10733,10566],{"class":284},[73,10735,1369],{"class":82},[73,10737,10738,10740,10742,10744,10747],{"class":75,"line":1918},[73,10739,6124],{"class":89},[73,10741,10698],{"class":686},[73,10743,90],{"class":89},[73,10745,10746],{"class":79}," 150",[73,10748,1382],{"class":82},[73,10750,10751],{"class":75,"line":1927},[73,10752,10753],{"class":82},"    \n",[73,10755,10756,10758,10760,10763,10766,10768,10770,10772,10774,10777,10779,10781],{"class":75,"line":1935},[73,10757,4672],{"class":89},[73,10759,496],{"class":82},[73,10761,10762],{"class":89},"public",[73,10764,10765],{"class":686}," name",[73,10767,690],{"class":89},[73,10769,2608],{"class":79},[73,10771,726],{"class":82},[73,10773,10762],{"class":89},[73,10775,10776],{"class":686}," age",[73,10778,690],{"class":89},[73,10780,7352],{"class":79},[73,10782,10783],{"class":82},") {}\n",[73,10785,10786],{"class":75,"line":1943},[73,10787,10753],{"class":82},[73,10789,10790,10792],{"class":75,"line":1952},[73,10791,10595],{"class":284},[73,10793,1530],{"class":82},[73,10795,10796,10798,10801,10803,10805,10807,10809],{"class":75,"line":1966},[73,10797,3601],{"class":89},[73,10799,10800],{"class":992}," `Hi, I'm ${",[73,10802,867],{"class":79},[73,10804,484],{"class":992},[73,10806,2489],{"class":82},[73,10808,3108],{"class":992},[73,10810,1382],{"class":82},[73,10812,10813],{"class":75,"line":2987},[73,10814,2984],{"class":82},[73,10816,10817],{"class":75,"line":2992},[73,10818,10753],{"class":82},[73,10820,10821,10823,10826,10828,10830,10832,10834,10836,10838,10840,10842,10844,10846,10848],{"class":75,"line":2998},[73,10822,6124],{"class":89},[73,10824,10825],{"class":284}," create",[73,10827,496],{"class":82},[73,10829,2489],{"class":686},[73,10831,690],{"class":89},[73,10833,2608],{"class":79},[73,10835,726],{"class":82},[73,10837,10642],{"class":686},[73,10839,690],{"class":89},[73,10841,7352],{"class":79},[73,10843,4316],{"class":82},[73,10845,690],{"class":89},[73,10847,10566],{"class":284},[73,10849,1369],{"class":82},[73,10851,10852,10854,10856,10858],{"class":75,"line":3013},[73,10853,3601],{"class":89},[73,10855,281],{"class":89},[73,10857,10728],{"class":284},[73,10859,10860],{"class":82},"(name, age);\n",[73,10862,10863],{"class":75,"line":3018},[73,10864,2984],{"class":82},[73,10866,10867],{"class":75,"line":3023},[73,10868,746],{"class":82},[73,10870,10871],{"class":75,"line":3029},[73,10872,437],{"emptyLinePlaceholder":436},[73,10874,10875],{"class":75,"line":3037},[73,10876,10877],{"class":291},"\u002F\u002F 4. 用构造函数接口约束类本身\n",[73,10879,10880,10882,10885,10887,10889,10891,10894],{"class":75,"line":3042},[73,10881,423],{"class":89},[73,10883,10884],{"class":79}," UserClass",[73,10886,690],{"class":89},[73,10888,10623],{"class":284},[73,10890,90],{"class":89},[73,10892,10893],{"class":82}," UserImpl;   ",[73,10895,10896],{"class":291},"\u002F\u002F ✅\n",[10,10898,10899],{},"这样的方式可以让我们解耦接口和实现，还支持依赖注入、工厂函数和类统一。以及还忘记提了，可以仿照Promise一样，使用declare var Promise: PromiseConstructor",[10,10901,10902],{},"这是lib.es2015.promise.d.ts里的做法，用一个var声明把值（构造函数）和类型（实例）分开，这个是ts声明库类型时的经典模式。",[64,10904,10906],{"className":1157,"code":10905,"language":1159,"meta":69,"style":69},"\u002F\u002F ===== 1. 实例接口 =====\ninterface Promise\u003CT> {\n    then\u003CTResult1 = T, TResult2 = never>(\n        onfulfilled?: ((value: T) => TResult1 | PromiseLike\u003CTResult1>) | null,\n        onrejected?: ((reason: any) => TResult2 | PromiseLike\u003CTResult2>) | null\n    ): Promise\u003CTResult1 | TResult2>;\n    catch\u003CTResult = never>(\n        onrejected?: ((reason: any) => TResult | PromiseLike\u003CTResult>) | null\n    ): Promise\u003CT | TResult>;\n    finally(onfinally?: (() => void) | null): Promise\u003CT>;\n    readonly [Symbol.toStringTag]: string;\n}\n\n\u002F\u002F ===== 2. 构造函数接口 =====\ninterface PromiseConstructor {\n    readonly prototype: Promise\u003Cany>;\n    \n    \u002F\u002F new 签名\n    new \u003CT>(\n        executor: (\n            resolve: (value: T | PromiseLike\u003CT>) => void,\n            reject: (reason?: any) => void\n        ) => void\n    ): Promise\u003CT>;\n    \n    \u002F\u002F 静态方法\n    resolve(): Promise\u003Cvoid>;\n    resolve\u003CT>(value: T | PromiseLike\u003CT>): Promise\u003CT>;\n    reject\u003CT = never>(reason?: any): Promise\u003CT>;\n    all\u003CT extends readonly unknown[] | []>(values: T): Promise\u003C...>;\n    race\u003CT>(values: Iterable\u003CT | PromiseLike\u003CT>>): Promise\u003CT>;\n    allSettled\u003CT>(values: Iterable\u003CT | PromiseLike\u003CT>>): Promise\u003C...>;\n    any\u003CT>(values: Iterable\u003CT | PromiseLike\u003CT>>): Promise\u003CT>;\n}\n\n\u002F\u002F ===== 3. 用 declare var 声明\"值\" =====\ndeclare var Promise: PromiseConstructor;\n",[26,10907,10908,10913,10926,10948,10986,11021,11039,11053,11087,11105,11142,11155,11159,11163,11168,11177,11194,11198,11203,11213,11221,11251,11271,11279,11293,11297,11301,11318,11354,11386,11427,11470,11507,11548,11552,11556,11561],{"__ignoreMap":69},[73,10909,10910],{"class":75,"line":76},[73,10911,10912],{"class":291},"\u002F\u002F ===== 1. 实例接口 =====\n",[73,10914,10915,10917,10920,10922,10924],{"class":75,"line":102},[73,10916,1363],{"class":89},[73,10918,10919],{"class":284}," Promise",[73,10921,1089],{"class":82},[73,10923,4218],{"class":284},[73,10925,4221],{"class":82},[73,10927,10928,10930,10932,10934,10936,10938,10940,10942,10944,10946],{"class":75,"line":120},[73,10929,3883],{"class":284},[73,10931,1089],{"class":82},[73,10933,3943],{"class":284},[73,10935,90],{"class":89},[73,10937,3893],{"class":284},[73,10939,726],{"class":82},[73,10941,3985],{"class":284},[73,10943,90],{"class":89},[73,10945,3901],{"class":79},[73,10947,4370],{"class":82},[73,10949,10950,10953,10955,10957,10959,10961,10963,10965,10967,10969,10971,10974,10976,10978,10980,10982,10984],{"class":75,"line":139},[73,10951,10952],{"class":686},"        onfulfilled",[73,10954,3915],{"class":89},[73,10956,3918],{"class":82},[73,10958,687],{"class":686},[73,10960,690],{"class":89},[73,10962,3893],{"class":284},[73,10964,3927],{"class":82},[73,10966,1766],{"class":89},[73,10968,4391],{"class":284},[73,10970,4059],{"class":89},[73,10972,10973],{"class":284}," PromiseLike",[73,10975,1089],{"class":82},[73,10977,3943],{"class":284},[73,10979,4402],{"class":82},[73,10981,3935],{"class":89},[73,10983,344],{"class":79},[73,10985,3073],{"class":82},[73,10987,10988,10991,10993,10995,10997,10999,11001,11003,11005,11007,11009,11011,11013,11015,11017,11019],{"class":75,"line":159},[73,10989,10990],{"class":686},"        onrejected",[73,10992,3915],{"class":89},[73,10994,3918],{"class":82},[73,10996,3965],{"class":686},[73,10998,690],{"class":89},[73,11000,2749],{"class":79},[73,11002,3927],{"class":82},[73,11004,1766],{"class":89},[73,11006,4008],{"class":284},[73,11008,4059],{"class":89},[73,11010,10973],{"class":284},[73,11012,1089],{"class":82},[73,11014,3985],{"class":284},[73,11016,4402],{"class":82},[73,11018,3935],{"class":89},[73,11020,3994],{"class":79},[73,11022,11023,11025,11027,11029,11031,11033,11035,11037],{"class":75,"line":178},[73,11024,4447],{"class":82},[73,11026,690],{"class":89},[73,11028,10919],{"class":284},[73,11030,1089],{"class":82},[73,11032,3943],{"class":284},[73,11034,4059],{"class":89},[73,11036,4008],{"class":284},[73,11038,4462],{"class":82},[73,11040,11041,11043,11045,11047,11049,11051],{"class":75,"line":204},[73,11042,4471],{"class":284},[73,11044,1089],{"class":82},[73,11046,4476],{"class":284},[73,11048,90],{"class":89},[73,11050,3901],{"class":79},[73,11052,4370],{"class":82},[73,11054,11055,11057,11059,11061,11063,11065,11067,11069,11071,11073,11075,11077,11079,11081,11083,11085],{"class":75,"line":1198},[73,11056,10990],{"class":686},[73,11058,3915],{"class":89},[73,11060,3918],{"class":82},[73,11062,3965],{"class":686},[73,11064,690],{"class":89},[73,11066,2749],{"class":79},[73,11068,3927],{"class":82},[73,11070,1766],{"class":89},[73,11072,4503],{"class":284},[73,11074,4059],{"class":89},[73,11076,10973],{"class":284},[73,11078,1089],{"class":82},[73,11080,4476],{"class":284},[73,11082,4402],{"class":82},[73,11084,3935],{"class":89},[73,11086,3994],{"class":79},[73,11088,11089,11091,11093,11095,11097,11099,11101,11103],{"class":75,"line":1203},[73,11090,4447],{"class":82},[73,11092,690],{"class":89},[73,11094,10919],{"class":284},[73,11096,1089],{"class":82},[73,11098,4218],{"class":284},[73,11100,4059],{"class":89},[73,11102,4503],{"class":284},[73,11104,4462],{"class":82},[73,11106,11107,11110,11112,11115,11117,11120,11122,11124,11126,11128,11130,11132,11134,11136,11138,11140],{"class":75,"line":1209},[73,11108,11109],{"class":284},"    finally",[73,11111,496],{"class":82},[73,11113,11114],{"class":686},"onfinally",[73,11116,3915],{"class":89},[73,11118,11119],{"class":82}," (() ",[73,11121,1766],{"class":89},[73,11123,4270],{"class":79},[73,11125,3927],{"class":82},[73,11127,3935],{"class":89},[73,11129,344],{"class":79},[73,11131,4316],{"class":82},[73,11133,690],{"class":89},[73,11135,10919],{"class":284},[73,11137,1089],{"class":82},[73,11139,4218],{"class":284},[73,11141,4462],{"class":82},[73,11143,11144,11146,11149,11151,11153],{"class":75,"line":1215},[73,11145,2644],{"class":89},[73,11147,11148],{"class":82}," [Symbol.toStringTag]",[73,11150,690],{"class":89},[73,11152,2608],{"class":79},[73,11154,1382],{"class":82},[73,11156,11157],{"class":75,"line":1221},[73,11158,746],{"class":82},[73,11160,11161],{"class":75,"line":1227},[73,11162,437],{"emptyLinePlaceholder":436},[73,11164,11165],{"class":75,"line":1233},[73,11166,11167],{"class":291},"\u002F\u002F ===== 2. 构造函数接口 =====\n",[73,11169,11170,11172,11175],{"class":75,"line":1899},[73,11171,1363],{"class":89},[73,11173,11174],{"class":284}," PromiseConstructor",[73,11176,1369],{"class":82},[73,11178,11179,11181,11183,11185,11187,11189,11192],{"class":75,"line":1913},[73,11180,2644],{"class":89},[73,11182,2647],{"class":686},[73,11184,690],{"class":89},[73,11186,10919],{"class":284},[73,11188,1089],{"class":82},[73,11190,11191],{"class":79},"any",[73,11193,4462],{"class":82},[73,11195,11196],{"class":75,"line":1918},[73,11197,10753],{"class":82},[73,11199,11200],{"class":75,"line":1927},[73,11201,11202],{"class":291},"    \u002F\u002F new 签名\n",[73,11204,11205,11207,11209,11211],{"class":75,"line":1935},[73,11206,2595],{"class":89},[73,11208,7368],{"class":82},[73,11210,4218],{"class":284},[73,11212,4370],{"class":82},[73,11214,11215,11217,11219],{"class":75,"line":1943},[73,11216,4679],{"class":284},[73,11218,690],{"class":89},[73,11220,4684],{"class":82},[73,11222,11223,11225,11227,11229,11231,11233,11235,11237,11239,11241,11243,11245,11247,11249],{"class":75,"line":1952},[73,11224,4689],{"class":284},[73,11226,690],{"class":89},[73,11228,2224],{"class":82},[73,11230,687],{"class":686},[73,11232,690],{"class":89},[73,11234,3893],{"class":284},[73,11236,4059],{"class":89},[73,11238,10973],{"class":284},[73,11240,1089],{"class":82},[73,11242,4218],{"class":284},[73,11244,4402],{"class":82},[73,11246,1766],{"class":89},[73,11248,4270],{"class":79},[73,11250,3073],{"class":82},[73,11252,11253,11255,11257,11259,11261,11263,11265,11267,11269],{"class":75,"line":1966},[73,11254,4712],{"class":284},[73,11256,690],{"class":89},[73,11258,2224],{"class":82},[73,11260,3965],{"class":686},[73,11262,3915],{"class":89},[73,11264,2749],{"class":79},[73,11266,3927],{"class":82},[73,11268,1766],{"class":89},[73,11270,4729],{"class":79},[73,11272,11273,11275,11277],{"class":75,"line":2987},[73,11274,4734],{"class":82},[73,11276,1766],{"class":89},[73,11278,4729],{"class":79},[73,11280,11281,11283,11285,11287,11289,11291],{"class":75,"line":2992},[73,11282,4447],{"class":82},[73,11284,690],{"class":89},[73,11286,10919],{"class":284},[73,11288,1089],{"class":82},[73,11290,4218],{"class":284},[73,11292,4462],{"class":82},[73,11294,11295],{"class":75,"line":2998},[73,11296,10753],{"class":82},[73,11298,11299],{"class":75,"line":3013},[73,11300,7672],{"class":291},[73,11302,11303,11305,11307,11309,11311,11313,11316],{"class":75,"line":3018},[73,11304,4305],{"class":284},[73,11306,7579],{"class":82},[73,11308,690],{"class":89},[73,11310,10919],{"class":284},[73,11312,1089],{"class":82},[73,11314,11315],{"class":79},"void",[73,11317,4462],{"class":82},[73,11319,11320,11322,11324,11326,11328,11330,11332,11334,11336,11338,11340,11342,11344,11346,11348,11350,11352],{"class":75,"line":3023},[73,11321,4305],{"class":284},[73,11323,1089],{"class":82},[73,11325,4218],{"class":284},[73,11327,6133],{"class":82},[73,11329,687],{"class":686},[73,11331,690],{"class":89},[73,11333,3893],{"class":284},[73,11335,4059],{"class":89},[73,11337,10973],{"class":284},[73,11339,1089],{"class":82},[73,11341,4218],{"class":284},[73,11343,7467],{"class":82},[73,11345,690],{"class":89},[73,11347,10919],{"class":284},[73,11349,1089],{"class":82},[73,11351,4218],{"class":284},[73,11353,4462],{"class":82},[73,11355,11356,11358,11360,11362,11364,11366,11368,11370,11372,11374,11376,11378,11380,11382,11384],{"class":75,"line":3029},[73,11357,4327],{"class":284},[73,11359,1089],{"class":82},[73,11361,4218],{"class":284},[73,11363,90],{"class":89},[73,11365,3901],{"class":79},[73,11367,6133],{"class":82},[73,11369,3965],{"class":686},[73,11371,3915],{"class":89},[73,11373,2749],{"class":79},[73,11375,4316],{"class":82},[73,11377,690],{"class":89},[73,11379,10919],{"class":284},[73,11381,1089],{"class":82},[73,11383,4218],{"class":284},[73,11385,4462],{"class":82},[73,11387,11388,11391,11393,11395,11398,11401,11403,11406,11408,11411,11414,11416,11418,11420,11422,11424],{"class":75,"line":3037},[73,11389,11390],{"class":284},"    all",[73,11392,1089],{"class":82},[73,11394,4218],{"class":284},[73,11396,11397],{"class":89}," extends",[73,11399,11400],{"class":89}," readonly",[73,11402,693],{"class":79},[73,11404,11405],{"class":82},"[] ",[73,11407,3935],{"class":89},[73,11409,11410],{"class":82}," []>(",[73,11412,11413],{"class":686},"values",[73,11415,690],{"class":89},[73,11417,3893],{"class":284},[73,11419,4316],{"class":82},[73,11421,690],{"class":89},[73,11423,10919],{"class":284},[73,11425,11426],{"class":82},"\u003C...>;\n",[73,11428,11429,11432,11434,11436,11438,11440,11442,11445,11447,11449,11451,11453,11455,11457,11460,11462,11464,11466,11468],{"class":75,"line":3042},[73,11430,11431],{"class":284},"    race",[73,11433,1089],{"class":82},[73,11435,4218],{"class":284},[73,11437,6133],{"class":82},[73,11439,11413],{"class":686},[73,11441,690],{"class":89},[73,11443,11444],{"class":284}," Iterable",[73,11446,1089],{"class":82},[73,11448,4218],{"class":284},[73,11450,4059],{"class":89},[73,11452,10973],{"class":284},[73,11454,1089],{"class":82},[73,11456,4218],{"class":284},[73,11458,11459],{"class":82},">>)",[73,11461,690],{"class":89},[73,11463,10919],{"class":284},[73,11465,1089],{"class":82},[73,11467,4218],{"class":284},[73,11469,4462],{"class":82},[73,11471,11472,11475,11477,11479,11481,11483,11485,11487,11489,11491,11493,11495,11497,11499,11501,11503,11505],{"class":75,"line":3047},[73,11473,11474],{"class":284},"    allSettled",[73,11476,1089],{"class":82},[73,11478,4218],{"class":284},[73,11480,6133],{"class":82},[73,11482,11413],{"class":686},[73,11484,690],{"class":89},[73,11486,11444],{"class":284},[73,11488,1089],{"class":82},[73,11490,4218],{"class":284},[73,11492,4059],{"class":89},[73,11494,10973],{"class":284},[73,11496,1089],{"class":82},[73,11498,4218],{"class":284},[73,11500,11459],{"class":82},[73,11502,690],{"class":89},[73,11504,10919],{"class":284},[73,11506,11426],{"class":82},[73,11508,11509,11512,11514,11516,11518,11520,11522,11524,11526,11528,11530,11532,11534,11536,11538,11540,11542,11544,11546],{"class":75,"line":3053},[73,11510,11511],{"class":284},"    any",[73,11513,1089],{"class":82},[73,11515,4218],{"class":284},[73,11517,6133],{"class":82},[73,11519,11413],{"class":686},[73,11521,690],{"class":89},[73,11523,11444],{"class":284},[73,11525,1089],{"class":82},[73,11527,4218],{"class":284},[73,11529,4059],{"class":89},[73,11531,10973],{"class":284},[73,11533,1089],{"class":82},[73,11535,4218],{"class":284},[73,11537,11459],{"class":82},[73,11539,690],{"class":89},[73,11541,10919],{"class":284},[73,11543,1089],{"class":82},[73,11545,4218],{"class":284},[73,11547,4462],{"class":82},[73,11549,11550],{"class":75,"line":3064},[73,11551,746],{"class":82},[73,11553,11554],{"class":75,"line":3076},[73,11555,437],{"emptyLinePlaceholder":436},[73,11557,11558],{"class":75,"line":3089},[73,11559,11560],{"class":291},"\u002F\u002F ===== 3. 用 declare var 声明\"值\" =====\n",[73,11562,11563,11565,11567,11569,11571,11573],{"class":75,"line":3114},[73,11564,2666],{"class":89},[73,11566,2669],{"class":89},[73,11568,10919],{"class":82},[73,11570,690],{"class":89},[73,11572,11174],{"class":284},[73,11574,1382],{"class":82},[10,11576,11577],{},"这种三段式方法很有用，declare var....这种一般用来告诉ts运行时有个全局变量叫做Promsie，类型为PromiseConsturctor，但是声明不会生成代码，如果没有declare的话，ts就把他当做变量声明了，导致结果就是编译成js，代码执行，全局Promise覆盖为undefined。",[11579,11580,11581],"style",{},"html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}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 .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":69,"searchDepth":102,"depth":102,"links":11583},[11584,11585,11586,11587,11588,11589,11590,11591,11592,11593,11594,11595,11596,11597,11598,11599,11600,11601,11602],{"id":16,"depth":120,"text":17},{"id":265,"depth":120,"text":265},{"id":775,"depth":120,"text":775},{"id":1445,"depth":120,"text":1445},{"id":1989,"depth":120,"text":1990},{"id":2450,"depth":120,"text":2450},{"id":2683,"depth":120,"text":2683},{"id":2702,"depth":120,"text":2702},{"id":493,"depth":120,"text":493},{"id":3645,"depth":120,"text":3645},{"id":3842,"depth":120,"text":3842},{"id":6345,"depth":120,"text":6345},{"id":6940,"depth":120,"text":6940},{"id":7710,"depth":120,"text":7710},{"id":7716,"depth":120,"text":7716},{"id":2344,"depth":120,"text":2344},{"id":10326,"depth":120,"text":10327},{"id":10387,"depth":120,"text":10388},{"id":10542,"depth":120,"text":10543},"md",{"date":11605,"tags":11606},"2026-12-10",[11607],"javascript","\u002Fjavascript\u002Fjs面试部分内容摘选",{"description":12},"javascript\u002Fjs面试部分内容摘选","Ng9R-xUEv67uRomTqKO7DdXI-otdd5IXKR77kX4MX2U",1791871181219]