[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fdesign":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fdesign":3881,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fdesign":3907},{"source":4,"connector":5,"page":6},"sqlite","better-sqlite3",{"path":7,"title":8,"description":9,"category":10,"tags":11,"date":14,"pinned":15,"draft":15,"body":16,"seo":3877,"stem":3878,"id":3879,"extension":3880},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fdesign","设计模式","常见创建型、结构型、行为型模式在 JavaScript 中的实现示例。对象创建与继承见 原型与面向对象。","技能小册",[12,13],"javascript","design","2021-10-05",false,{"type":17,"value":18,"toc":3855},"minimark",[19,22,32,37,40,45,52,58,362,368,372,377,383,655,660,664,667,823,829,834,838,841,845,850,1101,1114,1118,1123,1319,1324,1417,1422,1426,1435,1735,1740,1744,1753,2158,2167,2171,2174,2178,2187,2196,2430,2435,2439,2444,2646,2651,2655,2664,2862,2871,2875,2880,3152,3157,3161,3166,3595,3600,3603,3791,3794,3797,3800,3851],[20,21,8],"h1",{"id":8},[23,24,25,26,31],"p",{},"常见创建型、结构型、行为型模式在 JavaScript 中的实现示例。对象创建与继承见 ",[27,28,30],"a",{"href":29},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fprototype","原型与面向对象","。",[33,34,36],"h2",{"id":35},"一创建型模式","一、创建型模式",[23,38,39],{},"创建型模式关注对象如何被创建，隐藏创建逻辑，提升代码灵活性和复用性。",[41,42,44],"h3",{"id":43},"_1-单例模式singleton","1. 单例模式（Singleton）",[23,46,47,51],{},[48,49,50],"strong",{},"定义","：确保一个类只有一个实例，并提供一个全局访问点。",[23,53,54,57],{},[48,55,56],{},"实现","：利用闭包或 ES6 模块（模块本身就是单例）。",[59,60,65],"pre",{"className":61,"code":62,"language":63,"meta":64,"style":64},"language-js shiki shiki-themes material-theme-lighter github-light github-dark","\u002F\u002F 方式1：闭包\nconst Singleton = (function () {\n    let instance;\n    function init() {\n        return { name: \"I am the only one\" };\n    }\n    return {\n        getInstance() {\n            if (!instance) instance = init();\n            return instance;\n        },\n    };\n})();\n\n\u002F\u002F 方式2：ES6 模块（推荐）\n\u002F\u002F singleton.js\nlet instance = null;\nexport default {\n    getInstance() {\n        if (!instance) instance = { data: \"shared\" };\n        return instance;\n    },\n};\n","js","",[66,67,68,77,106,118,133,164,170,178,189,216,226,232,238,249,256,262,268,286,297,307,341,350,356],"code",{"__ignoreMap":64},[69,70,73],"span",{"class":71,"line":72},"line",1,[69,74,76],{"class":75},"sutJx","\u002F\u002F 方式1：闭包\n",[69,78,80,84,88,92,96,99,103],{"class":71,"line":79},2,[69,81,83],{"class":82},"sbsja","const",[69,85,87],{"class":86},"s_hVV"," Singleton",[69,89,91],{"class":90},"smGrS"," =",[69,93,95],{"class":94},"su5hD"," (",[69,97,98],{"class":82},"function",[69,100,102],{"class":101},"sP7_E"," ()",[69,104,105],{"class":101}," {\n",[69,107,109,112,115],{"class":71,"line":108},3,[69,110,111],{"class":82},"    let",[69,113,114],{"class":94}," instance",[69,116,117],{"class":101},";\n",[69,119,121,124,128,131],{"class":71,"line":120},4,[69,122,123],{"class":82},"    function",[69,125,127],{"class":126},"sGLFI"," init",[69,129,130],{"class":101},"()",[69,132,105],{"class":101},[69,134,136,140,143,147,150,154,158,161],{"class":71,"line":135},5,[69,137,139],{"class":138},"sVHd0","        return",[69,141,142],{"class":101}," {",[69,144,146],{"class":145},"skxfh"," name",[69,148,149],{"class":101},":",[69,151,153],{"class":152},"sjJ54"," \"",[69,155,157],{"class":156},"s_sjI","I am the only one",[69,159,160],{"class":152},"\"",[69,162,163],{"class":101}," };\n",[69,165,167],{"class":71,"line":166},6,[69,168,169],{"class":101},"    }\n",[69,171,173,176],{"class":71,"line":172},7,[69,174,175],{"class":138},"    return",[69,177,105],{"class":101},[69,179,181,185,187],{"class":71,"line":180},8,[69,182,184],{"class":183},"sVXei","        getInstance",[69,186,130],{"class":101},[69,188,105],{"class":101},[69,190,192,195,197,200,203,206,208,210,212,214],{"class":71,"line":191},9,[69,193,194],{"class":138},"            if",[69,196,95],{"class":145},[69,198,199],{"class":90},"!",[69,201,202],{"class":94},"instance",[69,204,205],{"class":145},") ",[69,207,202],{"class":94},[69,209,91],{"class":90},[69,211,127],{"class":126},[69,213,130],{"class":145},[69,215,117],{"class":101},[69,217,219,222,224],{"class":71,"line":218},10,[69,220,221],{"class":138},"            return",[69,223,114],{"class":94},[69,225,117],{"class":101},[69,227,229],{"class":71,"line":228},11,[69,230,231],{"class":101},"        },\n",[69,233,235],{"class":71,"line":234},12,[69,236,237],{"class":101},"    };\n",[69,239,241,244,247],{"class":71,"line":240},13,[69,242,243],{"class":101},"}",[69,245,246],{"class":94},")()",[69,248,117],{"class":101},[69,250,252],{"class":71,"line":251},14,[69,253,255],{"emptyLinePlaceholder":254},true,"\n",[69,257,259],{"class":71,"line":258},15,[69,260,261],{"class":75},"\u002F\u002F 方式2：ES6 模块（推荐）\n",[69,263,265],{"class":71,"line":264},16,[69,266,267],{"class":75},"\u002F\u002F singleton.js\n",[69,269,271,274,277,280,284],{"class":71,"line":270},17,[69,272,273],{"class":82},"let",[69,275,276],{"class":94}," instance ",[69,278,279],{"class":90},"=",[69,281,283],{"class":282},"s39Yj"," null",[69,285,117],{"class":101},[69,287,289,292,295],{"class":71,"line":288},18,[69,290,291],{"class":138},"export",[69,293,294],{"class":138}," default",[69,296,105],{"class":101},[69,298,300,303,305],{"class":71,"line":299},19,[69,301,302],{"class":183},"    getInstance",[69,304,130],{"class":101},[69,306,105],{"class":101},[69,308,310,313,315,317,319,321,323,325,327,330,332,334,337,339],{"class":71,"line":309},20,[69,311,312],{"class":138},"        if",[69,314,95],{"class":145},[69,316,199],{"class":90},[69,318,202],{"class":94},[69,320,205],{"class":145},[69,322,202],{"class":94},[69,324,91],{"class":90},[69,326,142],{"class":101},[69,328,329],{"class":145}," data",[69,331,149],{"class":101},[69,333,153],{"class":152},[69,335,336],{"class":156},"shared",[69,338,160],{"class":152},[69,340,163],{"class":101},[69,342,344,346,348],{"class":71,"line":343},21,[69,345,139],{"class":138},[69,347,114],{"class":94},[69,349,117],{"class":101},[69,351,353],{"class":71,"line":352},22,[69,354,355],{"class":101},"    },\n",[69,357,359],{"class":71,"line":358},23,[69,360,361],{"class":101},"};\n",[23,363,364,367],{},[48,365,366],{},"应用场景","：全局状态管理（Vuex \u002F Redux store）、日志记录器、线程池。",[41,369,371],{"id":370},"_2-工厂模式factory","2. 工厂模式（Factory）",[23,373,374,376],{},[48,375,50],{},"：定义一个创建对象的接口，由子类或具体工厂类决定实例化哪个类。简单工厂、工厂方法和抽象工厂。",[23,378,379,382],{},[48,380,381],{},"简单工厂示例","：",[59,384,386],{"className":61,"code":385,"language":63,"meta":64,"style":64},"class Button {\n    render() {\n        console.log(\"render button\");\n    }\n}\nclass Input {\n    render() {\n        console.log(\"render input\");\n    }\n}\nclass ComponentFactory {\n    static create(type) {\n        switch (type) {\n            case \"button\":\n                return new Button();\n            case \"input\":\n                return new Input();\n            default:\n                throw new Error(\"Unknown type\");\n        }\n    }\n}\nconst btn = ComponentFactory.create(\"button\");\n",[66,387,388,399,408,434,438,443,452,460,481,485,489,498,516,530,545,559,572,584,591,614,619,623,627],{"__ignoreMap":64},[69,389,390,393,397],{"class":71,"line":72},[69,391,392],{"class":82},"class",[69,394,396],{"class":395},"sbgvK"," Button",[69,398,105],{"class":101},[69,400,401,404,406],{"class":71,"line":79},[69,402,403],{"class":183},"    render",[69,405,130],{"class":101},[69,407,105],{"class":101},[69,409,410,413,416,419,422,424,427,429,432],{"class":71,"line":108},[69,411,412],{"class":94},"        console",[69,414,415],{"class":101},".",[69,417,418],{"class":126},"log",[69,420,421],{"class":145},"(",[69,423,160],{"class":152},[69,425,426],{"class":156},"render button",[69,428,160],{"class":152},[69,430,431],{"class":145},")",[69,433,117],{"class":101},[69,435,436],{"class":71,"line":120},[69,437,169],{"class":101},[69,439,440],{"class":71,"line":135},[69,441,442],{"class":101},"}\n",[69,444,445,447,450],{"class":71,"line":166},[69,446,392],{"class":82},[69,448,449],{"class":395}," Input",[69,451,105],{"class":101},[69,453,454,456,458],{"class":71,"line":172},[69,455,403],{"class":183},[69,457,130],{"class":101},[69,459,105],{"class":101},[69,461,462,464,466,468,470,472,475,477,479],{"class":71,"line":180},[69,463,412],{"class":94},[69,465,415],{"class":101},[69,467,418],{"class":126},[69,469,421],{"class":145},[69,471,160],{"class":152},[69,473,474],{"class":156},"render input",[69,476,160],{"class":152},[69,478,431],{"class":145},[69,480,117],{"class":101},[69,482,483],{"class":71,"line":191},[69,484,169],{"class":101},[69,486,487],{"class":71,"line":218},[69,488,442],{"class":101},[69,490,491,493,496],{"class":71,"line":228},[69,492,392],{"class":82},[69,494,495],{"class":395}," ComponentFactory",[69,497,105],{"class":101},[69,499,500,503,506,508,512,514],{"class":71,"line":234},[69,501,502],{"class":82},"    static",[69,504,505],{"class":183}," create",[69,507,421],{"class":101},[69,509,511],{"class":510},"s99_P","type",[69,513,431],{"class":101},[69,515,105],{"class":101},[69,517,518,521,523,525,527],{"class":71,"line":240},[69,519,520],{"class":138},"        switch",[69,522,95],{"class":145},[69,524,511],{"class":94},[69,526,205],{"class":145},[69,528,529],{"class":101},"{\n",[69,531,532,535,537,540,542],{"class":71,"line":251},[69,533,534],{"class":138},"            case",[69,536,153],{"class":152},[69,538,539],{"class":156},"button",[69,541,160],{"class":152},[69,543,544],{"class":101},":\n",[69,546,547,550,553,555,557],{"class":71,"line":258},[69,548,549],{"class":138},"                return",[69,551,552],{"class":90}," new",[69,554,396],{"class":126},[69,556,130],{"class":145},[69,558,117],{"class":101},[69,560,561,563,565,568,570],{"class":71,"line":264},[69,562,534],{"class":138},[69,564,153],{"class":152},[69,566,567],{"class":156},"input",[69,569,160],{"class":152},[69,571,544],{"class":101},[69,573,574,576,578,580,582],{"class":71,"line":270},[69,575,549],{"class":138},[69,577,552],{"class":90},[69,579,449],{"class":126},[69,581,130],{"class":145},[69,583,117],{"class":101},[69,585,586,589],{"class":71,"line":288},[69,587,588],{"class":138},"            default",[69,590,544],{"class":101},[69,592,593,596,598,601,603,605,608,610,612],{"class":71,"line":299},[69,594,595],{"class":138},"                throw",[69,597,552],{"class":90},[69,599,600],{"class":126}," Error",[69,602,421],{"class":145},[69,604,160],{"class":152},[69,606,607],{"class":156},"Unknown type",[69,609,160],{"class":152},[69,611,431],{"class":145},[69,613,117],{"class":101},[69,615,616],{"class":71,"line":309},[69,617,618],{"class":101},"        }\n",[69,620,621],{"class":71,"line":343},[69,622,169],{"class":101},[69,624,625],{"class":71,"line":352},[69,626,442],{"class":101},[69,628,629,631,634,636,638,640,643,645,647,649,651,653],{"class":71,"line":358},[69,630,83],{"class":82},[69,632,633],{"class":86}," btn",[69,635,91],{"class":90},[69,637,495],{"class":94},[69,639,415],{"class":101},[69,641,642],{"class":126},"create",[69,644,421],{"class":94},[69,646,160],{"class":152},[69,648,539],{"class":156},[69,650,160],{"class":152},[69,652,431],{"class":94},[69,654,117],{"class":101},[23,656,657,659],{},[48,658,366],{},"：根据配置动态创建 UI 组件、数据模型解析。",[41,661,663],{"id":662},"_3-构造函数-原型模式constructor-prototype","3. 构造函数 + 原型模式（Constructor & Prototype）",[23,665,666],{},"在 JavaScript 中，通过构造函数定义实例属性，通过原型定义共享方法，实现“类”的效果。这是 JS 原生的对象创建模式。",[59,668,670],{"className":61,"code":669,"language":63,"meta":64,"style":64},"function Person(name, age) {\n    this.name = name;\n    this.age = age;\n}\nPerson.prototype.sayHello = function () {\n    console.log(`Hello, I'm ${this.name}`);\n};\nconst p1 = new Person(\"Alice\", 25);\n",[66,671,672,694,709,724,728,753,787,791],{"__ignoreMap":64},[69,673,674,676,679,681,684,687,690,692],{"class":71,"line":72},[69,675,98],{"class":82},[69,677,678],{"class":126}," Person",[69,680,421],{"class":101},[69,682,683],{"class":510},"name",[69,685,686],{"class":101},",",[69,688,689],{"class":510}," age",[69,691,431],{"class":101},[69,693,105],{"class":101},[69,695,696,699,701,703,705,707],{"class":71,"line":79},[69,697,698],{"class":282},"    this",[69,700,415],{"class":101},[69,702,683],{"class":94},[69,704,91],{"class":90},[69,706,146],{"class":94},[69,708,117],{"class":101},[69,710,711,713,715,718,720,722],{"class":71,"line":108},[69,712,698],{"class":282},[69,714,415],{"class":101},[69,716,717],{"class":94},"age",[69,719,91],{"class":90},[69,721,689],{"class":94},[69,723,117],{"class":101},[69,725,726],{"class":71,"line":120},[69,727,442],{"class":101},[69,729,730,734,736,739,741,744,746,749,751],{"class":71,"line":135},[69,731,733],{"class":732},"sZMiF","Person",[69,735,415],{"class":101},[69,737,738],{"class":86},"prototype",[69,740,415],{"class":101},[69,742,743],{"class":126},"sayHello",[69,745,91],{"class":90},[69,747,748],{"class":82}," function",[69,750,102],{"class":101},[69,752,105],{"class":101},[69,754,755,758,760,762,764,767,770,773,776,778,780,783,785],{"class":71,"line":166},[69,756,757],{"class":94},"    console",[69,759,415],{"class":101},[69,761,418],{"class":126},[69,763,421],{"class":145},[69,765,766],{"class":152},"`",[69,768,769],{"class":156},"Hello, I'm ",[69,771,772],{"class":152},"${",[69,774,775],{"class":282},"this",[69,777,415],{"class":152},[69,779,683],{"class":94},[69,781,782],{"class":152},"}`",[69,784,431],{"class":145},[69,786,117],{"class":101},[69,788,789],{"class":71,"line":172},[69,790,361],{"class":101},[69,792,793,795,798,800,802,804,806,808,811,813,815,819,821],{"class":71,"line":180},[69,794,83],{"class":82},[69,796,797],{"class":86}," p1",[69,799,91],{"class":90},[69,801,552],{"class":90},[69,803,678],{"class":126},[69,805,421],{"class":94},[69,807,160],{"class":152},[69,809,810],{"class":156},"Alice",[69,812,160],{"class":152},[69,814,686],{"class":101},[69,816,818],{"class":817},"srdBf"," 25",[69,820,431],{"class":94},[69,822,117],{"class":101},[23,824,825,828],{},[48,826,827],{},"ES6 class 本质","就是构造函数的语法糖，结合原型链。",[23,830,831,833],{},[48,832,366],{},"：任何需要创建多个相似对象的场景，是 JS 面向对象的基础。",[33,835,837],{"id":836},"二结构型模式","二、结构型模式",[23,839,840],{},"结构型模式关注如何组合类和对象以形成更大的结构。",[41,842,844],{"id":843},"_1-适配器模式adapter","1. 适配器模式（Adapter）",[23,846,847,849],{},[48,848,50],{},"：将一个类的接口转换成客户端期望的另一个接口，使原本不兼容的类可以一起工作。",[59,851,853],{"className":61,"code":852,"language":63,"meta":64,"style":64},"\u002F\u002F 旧接口\nclass OldAPI {\n    request(data) {\n        return `Old: ${data}`;\n    }\n}\n\u002F\u002F 适配器：将旧接口适配成新接口\nclass Adapter {\n    constructor(oldApi) {\n        this.oldApi = oldApi;\n    }\n    newRequest(data) {\n        const result = this.oldApi.request(data);\n        return `Adapted: ${result}`;\n    }\n}\n\u002F\u002F 使用\nconst old = new OldAPI();\nconst adapted = new Adapter(old);\nconsole.log(adapted.newRequest(\"hello\")); \u002F\u002F Adapted: Old: hello\n",[66,854,855,860,869,883,901,905,909,914,923,937,953,957,970,1000,1018,1022,1026,1031,1048,1066],{"__ignoreMap":64},[69,856,857],{"class":71,"line":72},[69,858,859],{"class":75},"\u002F\u002F 旧接口\n",[69,861,862,864,867],{"class":71,"line":79},[69,863,392],{"class":82},[69,865,866],{"class":395}," OldAPI",[69,868,105],{"class":101},[69,870,871,874,876,879,881],{"class":71,"line":108},[69,872,873],{"class":183},"    request",[69,875,421],{"class":101},[69,877,878],{"class":510},"data",[69,880,431],{"class":101},[69,882,105],{"class":101},[69,884,885,887,890,893,895,897,899],{"class":71,"line":120},[69,886,139],{"class":138},[69,888,889],{"class":152}," `",[69,891,892],{"class":156},"Old: ",[69,894,772],{"class":152},[69,896,878],{"class":94},[69,898,782],{"class":152},[69,900,117],{"class":101},[69,902,903],{"class":71,"line":135},[69,904,169],{"class":101},[69,906,907],{"class":71,"line":166},[69,908,442],{"class":101},[69,910,911],{"class":71,"line":172},[69,912,913],{"class":75},"\u002F\u002F 适配器：将旧接口适配成新接口\n",[69,915,916,918,921],{"class":71,"line":180},[69,917,392],{"class":82},[69,919,920],{"class":395}," Adapter",[69,922,105],{"class":101},[69,924,925,928,930,933,935],{"class":71,"line":191},[69,926,927],{"class":82},"    constructor",[69,929,421],{"class":101},[69,931,932],{"class":510},"oldApi",[69,934,431],{"class":101},[69,936,105],{"class":101},[69,938,939,942,944,946,948,951],{"class":71,"line":218},[69,940,941],{"class":282},"        this",[69,943,415],{"class":101},[69,945,932],{"class":94},[69,947,91],{"class":90},[69,949,950],{"class":94}," oldApi",[69,952,117],{"class":101},[69,954,955],{"class":71,"line":228},[69,956,169],{"class":101},[69,958,959,962,964,966,968],{"class":71,"line":234},[69,960,961],{"class":183},"    newRequest",[69,963,421],{"class":101},[69,965,878],{"class":510},[69,967,431],{"class":101},[69,969,105],{"class":101},[69,971,972,975,978,980,983,985,987,989,992,994,996,998],{"class":71,"line":240},[69,973,974],{"class":82},"        const",[69,976,977],{"class":86}," result",[69,979,91],{"class":90},[69,981,982],{"class":282}," this",[69,984,415],{"class":101},[69,986,932],{"class":94},[69,988,415],{"class":101},[69,990,991],{"class":126},"request",[69,993,421],{"class":145},[69,995,878],{"class":94},[69,997,431],{"class":145},[69,999,117],{"class":101},[69,1001,1002,1004,1006,1009,1011,1014,1016],{"class":71,"line":251},[69,1003,139],{"class":138},[69,1005,889],{"class":152},[69,1007,1008],{"class":156},"Adapted: ",[69,1010,772],{"class":152},[69,1012,1013],{"class":94},"result",[69,1015,782],{"class":152},[69,1017,117],{"class":101},[69,1019,1020],{"class":71,"line":258},[69,1021,169],{"class":101},[69,1023,1024],{"class":71,"line":264},[69,1025,442],{"class":101},[69,1027,1028],{"class":71,"line":270},[69,1029,1030],{"class":75},"\u002F\u002F 使用\n",[69,1032,1033,1035,1038,1040,1042,1044,1046],{"class":71,"line":288},[69,1034,83],{"class":82},[69,1036,1037],{"class":86}," old",[69,1039,91],{"class":90},[69,1041,552],{"class":90},[69,1043,866],{"class":126},[69,1045,130],{"class":94},[69,1047,117],{"class":101},[69,1049,1050,1052,1055,1057,1059,1061,1064],{"class":71,"line":299},[69,1051,83],{"class":82},[69,1053,1054],{"class":86}," adapted",[69,1056,91],{"class":90},[69,1058,552],{"class":90},[69,1060,920],{"class":126},[69,1062,1063],{"class":94},"(old)",[69,1065,117],{"class":101},[69,1067,1068,1071,1073,1075,1078,1080,1083,1085,1087,1090,1092,1095,1098],{"class":71,"line":309},[69,1069,1070],{"class":94},"console",[69,1072,415],{"class":101},[69,1074,418],{"class":126},[69,1076,1077],{"class":94},"(adapted",[69,1079,415],{"class":101},[69,1081,1082],{"class":126},"newRequest",[69,1084,421],{"class":94},[69,1086,160],{"class":152},[69,1088,1089],{"class":156},"hello",[69,1091,160],{"class":152},[69,1093,1094],{"class":94},"))",[69,1096,1097],{"class":101},";",[69,1099,1100],{"class":75}," \u002F\u002F Adapted: Old: hello\n",[23,1102,1103,1105,1106,1109,1110,1113],{},[48,1104,366],{},"：封装浏览器 API 差异（如 ",[66,1107,1108],{},"XMLHttpRequest"," 与 ",[66,1111,1112],{},"fetch","）、第三方库接口统一。",[41,1115,1117],{"id":1116},"_2-装饰器模式decorator","2. 装饰器模式（Decorator）",[23,1119,1120,1122],{},[48,1121,50],{},"：动态地给对象添加额外职责，比继承更灵活。在 React 中高阶组件（HOC）就是装饰器思想。",[59,1124,1126],{"className":61,"code":1125,"language":63,"meta":64,"style":64},"\u002F\u002F 基础函数\nfunction log(message) {\n    console.log(message);\n}\n\u002F\u002F 装饰器：增加时间戳\nfunction withTimestamp(fn) {\n    return function (...args) {\n        const timestamp = new Date().toISOString();\n        fn(`[${timestamp}] ${args[0]}`);\n    };\n}\nconst decoratedLog = withTimestamp(log);\ndecoratedLog(\"Hello\"); \u002F\u002F 输出带时间戳的日志\n",[66,1127,1128,1133,1149,1165,1169,1174,1190,1208,1233,1274,1278,1282,1298],{"__ignoreMap":64},[69,1129,1130],{"class":71,"line":72},[69,1131,1132],{"class":75},"\u002F\u002F 基础函数\n",[69,1134,1135,1137,1140,1142,1145,1147],{"class":71,"line":79},[69,1136,98],{"class":82},[69,1138,1139],{"class":126}," log",[69,1141,421],{"class":101},[69,1143,1144],{"class":510},"message",[69,1146,431],{"class":101},[69,1148,105],{"class":101},[69,1150,1151,1153,1155,1157,1159,1161,1163],{"class":71,"line":108},[69,1152,757],{"class":94},[69,1154,415],{"class":101},[69,1156,418],{"class":126},[69,1158,421],{"class":145},[69,1160,1144],{"class":94},[69,1162,431],{"class":145},[69,1164,117],{"class":101},[69,1166,1167],{"class":71,"line":120},[69,1168,442],{"class":101},[69,1170,1171],{"class":71,"line":135},[69,1172,1173],{"class":75},"\u002F\u002F 装饰器：增加时间戳\n",[69,1175,1176,1178,1181,1183,1186,1188],{"class":71,"line":166},[69,1177,98],{"class":82},[69,1179,1180],{"class":126}," withTimestamp",[69,1182,421],{"class":101},[69,1184,1185],{"class":510},"fn",[69,1187,431],{"class":101},[69,1189,105],{"class":101},[69,1191,1192,1194,1196,1198,1201,1204,1206],{"class":71,"line":172},[69,1193,175],{"class":138},[69,1195,748],{"class":82},[69,1197,95],{"class":101},[69,1199,1200],{"class":90},"...",[69,1202,1203],{"class":510},"args",[69,1205,431],{"class":101},[69,1207,105],{"class":101},[69,1209,1210,1212,1215,1217,1219,1222,1224,1226,1229,1231],{"class":71,"line":180},[69,1211,974],{"class":82},[69,1213,1214],{"class":86}," timestamp",[69,1216,91],{"class":90},[69,1218,552],{"class":90},[69,1220,1221],{"class":126}," Date",[69,1223,130],{"class":145},[69,1225,415],{"class":101},[69,1227,1228],{"class":126},"toISOString",[69,1230,130],{"class":145},[69,1232,117],{"class":101},[69,1234,1235,1238,1240,1242,1245,1247,1250,1252,1255,1257,1259,1262,1265,1268,1270,1272],{"class":71,"line":191},[69,1236,1237],{"class":126},"        fn",[69,1239,421],{"class":145},[69,1241,766],{"class":152},[69,1243,1244],{"class":156},"[",[69,1246,772],{"class":152},[69,1248,1249],{"class":94},"timestamp",[69,1251,243],{"class":152},[69,1253,1254],{"class":156},"] ",[69,1256,772],{"class":152},[69,1258,1203],{"class":94},[69,1260,1244],{"class":1261},"sfo-9",[69,1263,1264],{"class":817},"0",[69,1266,1267],{"class":1261},"]",[69,1269,782],{"class":152},[69,1271,431],{"class":145},[69,1273,117],{"class":101},[69,1275,1276],{"class":71,"line":218},[69,1277,237],{"class":101},[69,1279,1280],{"class":71,"line":228},[69,1281,442],{"class":101},[69,1283,1284,1286,1289,1291,1293,1296],{"class":71,"line":234},[69,1285,83],{"class":82},[69,1287,1288],{"class":86}," decoratedLog",[69,1290,91],{"class":90},[69,1292,1180],{"class":126},[69,1294,1295],{"class":94},"(log)",[69,1297,117],{"class":101},[69,1299,1300,1303,1305,1307,1310,1312,1314,1316],{"class":71,"line":240},[69,1301,1302],{"class":126},"decoratedLog",[69,1304,421],{"class":94},[69,1306,160],{"class":152},[69,1308,1309],{"class":156},"Hello",[69,1311,160],{"class":152},[69,1313,431],{"class":94},[69,1315,1097],{"class":101},[69,1317,1318],{"class":75}," \u002F\u002F 输出带时间戳的日志\n",[23,1320,1321,382],{},[48,1322,1323],{},"React HOC 示例",[59,1325,1327],{"className":61,"code":1326,"language":63,"meta":64,"style":64},"function withAuth(Component) {\n    return function Authenticated(props) {\n        if (!props.isLoggedIn) return \u003CLoginPage \u002F>;\n        return \u003CComponent {...props} \u002F>;\n    };\n}\n",[66,1328,1329,1345,1363,1392,1409,1413],{"__ignoreMap":64},[69,1330,1331,1333,1336,1338,1341,1343],{"class":71,"line":72},[69,1332,98],{"class":82},[69,1334,1335],{"class":126}," withAuth",[69,1337,421],{"class":101},[69,1339,1340],{"class":510},"Component",[69,1342,431],{"class":101},[69,1344,105],{"class":101},[69,1346,1347,1349,1351,1354,1356,1359,1361],{"class":71,"line":79},[69,1348,175],{"class":138},[69,1350,748],{"class":82},[69,1352,1353],{"class":126}," Authenticated",[69,1355,421],{"class":101},[69,1357,1358],{"class":510},"props",[69,1360,431],{"class":101},[69,1362,105],{"class":101},[69,1364,1365,1367,1369,1371,1373,1375,1378,1380,1383,1386,1389],{"class":71,"line":108},[69,1366,312],{"class":138},[69,1368,95],{"class":145},[69,1370,199],{"class":90},[69,1372,1358],{"class":94},[69,1374,415],{"class":101},[69,1376,1377],{"class":94},"isLoggedIn",[69,1379,205],{"class":145},[69,1381,1382],{"class":138},"return",[69,1384,1385],{"class":101}," \u003C",[69,1387,1388],{"class":732},"LoginPage",[69,1390,1391],{"class":101}," \u002F>;\n",[69,1393,1394,1396,1398,1400,1402,1404,1406],{"class":71,"line":120},[69,1395,139],{"class":138},[69,1397,1385],{"class":101},[69,1399,1340],{"class":732},[69,1401,142],{"class":101},[69,1403,1200],{"class":90},[69,1405,1358],{"class":94},[69,1407,1408],{"class":101},"} \u002F>;\n",[69,1410,1411],{"class":71,"line":135},[69,1412,237],{"class":101},[69,1414,1415],{"class":71,"line":166},[69,1416,442],{"class":101},[23,1418,1419,1421],{},[48,1420,366],{},"：日志增强、权限控制、性能监控。",[41,1423,1425],{"id":1424},"_3-代理模式proxy","3. 代理模式（Proxy）",[23,1427,1428,1430,1431,1434],{},[48,1429,50],{},"：为其他对象提供一种代理以控制对这个对象的访问。JavaScript 的 ",[66,1432,1433],{},"Proxy"," 对象直接实现了该模式。",[59,1436,1438],{"className":61,"code":1437,"language":63,"meta":64,"style":64},"const target = { name: \"Alice\", age: 25 };\nconst handler = {\n    get(obj, prop) {\n        if (prop === \"age\") return obj[prop] + \" years old\";\n        return obj[prop];\n    },\n    set(obj, prop, value) {\n        if (prop === \"age\" && value \u003C 0) throw new Error(\"Age cannot be negative\");\n        obj[prop] = value;\n        return true;\n    },\n};\nconst proxy = new Proxy(target, handler);\nconsole.log(proxy.age); \u002F\u002F \"25 years old\"\nproxy.age = -1; \u002F\u002F Error\n",[66,1439,1440,1471,1482,1501,1544,1558,1562,1584,1632,1649,1659,1663,1667,1691,1712],{"__ignoreMap":64},[69,1441,1442,1444,1447,1449,1451,1453,1455,1457,1459,1461,1463,1465,1467,1469],{"class":71,"line":72},[69,1443,83],{"class":82},[69,1445,1446],{"class":86}," target",[69,1448,91],{"class":90},[69,1450,142],{"class":101},[69,1452,146],{"class":145},[69,1454,149],{"class":101},[69,1456,153],{"class":152},[69,1458,810],{"class":156},[69,1460,160],{"class":152},[69,1462,686],{"class":101},[69,1464,689],{"class":145},[69,1466,149],{"class":101},[69,1468,818],{"class":817},[69,1470,163],{"class":101},[69,1472,1473,1475,1478,1480],{"class":71,"line":79},[69,1474,83],{"class":82},[69,1476,1477],{"class":86}," handler",[69,1479,91],{"class":90},[69,1481,105],{"class":101},[69,1483,1484,1487,1489,1492,1494,1497,1499],{"class":71,"line":108},[69,1485,1486],{"class":183},"    get",[69,1488,421],{"class":101},[69,1490,1491],{"class":510},"obj",[69,1493,686],{"class":101},[69,1495,1496],{"class":510}," prop",[69,1498,431],{"class":101},[69,1500,105],{"class":101},[69,1502,1503,1505,1507,1510,1513,1515,1517,1519,1521,1523,1526,1528,1530,1532,1535,1537,1540,1542],{"class":71,"line":120},[69,1504,312],{"class":138},[69,1506,95],{"class":145},[69,1508,1509],{"class":94},"prop",[69,1511,1512],{"class":90}," ===",[69,1514,153],{"class":152},[69,1516,717],{"class":156},[69,1518,160],{"class":152},[69,1520,205],{"class":145},[69,1522,1382],{"class":138},[69,1524,1525],{"class":94}," obj",[69,1527,1244],{"class":145},[69,1529,1509],{"class":94},[69,1531,1254],{"class":145},[69,1533,1534],{"class":90},"+",[69,1536,153],{"class":152},[69,1538,1539],{"class":156}," years old",[69,1541,160],{"class":152},[69,1543,117],{"class":101},[69,1545,1546,1548,1550,1552,1554,1556],{"class":71,"line":135},[69,1547,139],{"class":138},[69,1549,1525],{"class":94},[69,1551,1244],{"class":145},[69,1553,1509],{"class":94},[69,1555,1267],{"class":145},[69,1557,117],{"class":101},[69,1559,1560],{"class":71,"line":166},[69,1561,355],{"class":101},[69,1563,1564,1567,1569,1571,1573,1575,1577,1580,1582],{"class":71,"line":172},[69,1565,1566],{"class":183},"    set",[69,1568,421],{"class":101},[69,1570,1491],{"class":510},[69,1572,686],{"class":101},[69,1574,1496],{"class":510},[69,1576,686],{"class":101},[69,1578,1579],{"class":510}," value",[69,1581,431],{"class":101},[69,1583,105],{"class":101},[69,1585,1586,1588,1590,1592,1594,1596,1598,1600,1603,1605,1607,1610,1612,1615,1617,1619,1621,1623,1626,1628,1630],{"class":71,"line":180},[69,1587,312],{"class":138},[69,1589,95],{"class":145},[69,1591,1509],{"class":94},[69,1593,1512],{"class":90},[69,1595,153],{"class":152},[69,1597,717],{"class":156},[69,1599,160],{"class":152},[69,1601,1602],{"class":90}," &&",[69,1604,1579],{"class":94},[69,1606,1385],{"class":90},[69,1608,1609],{"class":817}," 0",[69,1611,205],{"class":145},[69,1613,1614],{"class":138},"throw",[69,1616,552],{"class":90},[69,1618,600],{"class":126},[69,1620,421],{"class":145},[69,1622,160],{"class":152},[69,1624,1625],{"class":156},"Age cannot be negative",[69,1627,160],{"class":152},[69,1629,431],{"class":145},[69,1631,117],{"class":101},[69,1633,1634,1637,1639,1641,1643,1645,1647],{"class":71,"line":191},[69,1635,1636],{"class":94},"        obj",[69,1638,1244],{"class":145},[69,1640,1509],{"class":94},[69,1642,1254],{"class":145},[69,1644,279],{"class":90},[69,1646,1579],{"class":94},[69,1648,117],{"class":101},[69,1650,1651,1653,1657],{"class":71,"line":218},[69,1652,139],{"class":138},[69,1654,1656],{"class":1655},"syTEX"," true",[69,1658,117],{"class":101},[69,1660,1661],{"class":71,"line":228},[69,1662,355],{"class":101},[69,1664,1665],{"class":71,"line":234},[69,1666,361],{"class":101},[69,1668,1669,1671,1674,1676,1678,1681,1684,1686,1689],{"class":71,"line":240},[69,1670,83],{"class":82},[69,1672,1673],{"class":86}," proxy",[69,1675,91],{"class":90},[69,1677,552],{"class":90},[69,1679,1680],{"class":126}," Proxy",[69,1682,1683],{"class":94},"(target",[69,1685,686],{"class":101},[69,1687,1688],{"class":94}," handler)",[69,1690,117],{"class":101},[69,1692,1693,1695,1697,1699,1702,1704,1707,1709],{"class":71,"line":251},[69,1694,1070],{"class":94},[69,1696,415],{"class":101},[69,1698,418],{"class":126},[69,1700,1701],{"class":94},"(proxy",[69,1703,415],{"class":101},[69,1705,1706],{"class":94},"age)",[69,1708,1097],{"class":101},[69,1710,1711],{"class":75}," \u002F\u002F \"25 years old\"\n",[69,1713,1714,1717,1719,1722,1724,1727,1730,1732],{"class":71,"line":258},[69,1715,1716],{"class":94},"proxy",[69,1718,415],{"class":101},[69,1720,1721],{"class":94},"age ",[69,1723,279],{"class":90},[69,1725,1726],{"class":90}," -",[69,1728,1729],{"class":817},"1",[69,1731,1097],{"class":101},[69,1733,1734],{"class":75}," \u002F\u002F Error\n",[23,1736,1737,1739],{},[48,1738,366],{},"：Vue 3 响应式系统、数据校验、访问控制、缓存代理。",[41,1741,1743],{"id":1742},"_4-发布-订阅模式publish-subscribe与事件总线","4. 发布-订阅模式（Publish-Subscribe）与事件总线",[23,1745,1746,1748,1749,1752],{},[48,1747,50],{},"：发布者发布事件，订阅者监听事件，彼此解耦。不同于观察者模式（下面介绍），发布-订阅通常有一个",[48,1750,1751],{},"事件中心","作为调度器。",[59,1754,1756],{"className":61,"code":1755,"language":63,"meta":64,"style":64},"class EventBus {\n    constructor() {\n        this.events = {};\n    }\n    on(event, callback) {\n        if (!this.events[event]) this.events[event] = [];\n        this.events[event].push(callback);\n    }\n    emit(event, data) {\n        (this.events[event] || []).forEach(cb => cb(data));\n    }\n    off(event, callback) {\n        if (!callback) delete this.events[event];\n        else this.events[event] = this.events[event]?.filter(cb => cb !== callback);\n    }\n}\nconst bus = new EventBus();\nbus.on(\"userLogin\", user => console.log(`${user} logged in`));\nbus.emit(\"userLogin\", \"Alice\");\n",[66,1757,1758,1767,1775,1789,1793,1812,1852,1880,1884,1901,1948,1952,1969,1998,2052,2056,2060,2077,2129],{"__ignoreMap":64},[69,1759,1760,1762,1765],{"class":71,"line":72},[69,1761,392],{"class":82},[69,1763,1764],{"class":395}," EventBus",[69,1766,105],{"class":101},[69,1768,1769,1771,1773],{"class":71,"line":79},[69,1770,927],{"class":82},[69,1772,130],{"class":101},[69,1774,105],{"class":101},[69,1776,1777,1779,1781,1784,1786],{"class":71,"line":108},[69,1778,941],{"class":282},[69,1780,415],{"class":101},[69,1782,1783],{"class":94},"events",[69,1785,91],{"class":90},[69,1787,1788],{"class":101}," {};\n",[69,1790,1791],{"class":71,"line":120},[69,1792,169],{"class":101},[69,1794,1795,1798,1800,1803,1805,1808,1810],{"class":71,"line":135},[69,1796,1797],{"class":183},"    on",[69,1799,421],{"class":101},[69,1801,1802],{"class":510},"event",[69,1804,686],{"class":101},[69,1806,1807],{"class":510}," callback",[69,1809,431],{"class":101},[69,1811,105],{"class":101},[69,1813,1814,1816,1818,1820,1822,1824,1826,1828,1830,1833,1835,1837,1839,1841,1843,1845,1847,1850],{"class":71,"line":166},[69,1815,312],{"class":138},[69,1817,95],{"class":145},[69,1819,199],{"class":90},[69,1821,775],{"class":282},[69,1823,415],{"class":101},[69,1825,1783],{"class":94},[69,1827,1244],{"class":145},[69,1829,1802],{"class":94},[69,1831,1832],{"class":145},"]) ",[69,1834,775],{"class":282},[69,1836,415],{"class":101},[69,1838,1783],{"class":94},[69,1840,1244],{"class":145},[69,1842,1802],{"class":94},[69,1844,1254],{"class":145},[69,1846,279],{"class":90},[69,1848,1849],{"class":145}," []",[69,1851,117],{"class":101},[69,1853,1854,1856,1858,1860,1862,1864,1866,1868,1871,1873,1876,1878],{"class":71,"line":172},[69,1855,941],{"class":282},[69,1857,415],{"class":101},[69,1859,1783],{"class":94},[69,1861,1244],{"class":145},[69,1863,1802],{"class":94},[69,1865,1267],{"class":145},[69,1867,415],{"class":101},[69,1869,1870],{"class":126},"push",[69,1872,421],{"class":145},[69,1874,1875],{"class":94},"callback",[69,1877,431],{"class":145},[69,1879,117],{"class":101},[69,1881,1882],{"class":71,"line":180},[69,1883,169],{"class":101},[69,1885,1886,1889,1891,1893,1895,1897,1899],{"class":71,"line":191},[69,1887,1888],{"class":183},"    emit",[69,1890,421],{"class":101},[69,1892,1802],{"class":510},[69,1894,686],{"class":101},[69,1896,329],{"class":510},[69,1898,431],{"class":101},[69,1900,105],{"class":101},[69,1902,1903,1906,1908,1910,1912,1914,1916,1918,1921,1924,1926,1929,1931,1934,1937,1940,1942,1944,1946],{"class":71,"line":218},[69,1904,1905],{"class":145},"        (",[69,1907,775],{"class":282},[69,1909,415],{"class":101},[69,1911,1783],{"class":94},[69,1913,1244],{"class":145},[69,1915,1802],{"class":94},[69,1917,1254],{"class":145},[69,1919,1920],{"class":90},"||",[69,1922,1923],{"class":145}," [])",[69,1925,415],{"class":101},[69,1927,1928],{"class":126},"forEach",[69,1930,421],{"class":145},[69,1932,1933],{"class":510},"cb",[69,1935,1936],{"class":82}," =>",[69,1938,1939],{"class":126}," cb",[69,1941,421],{"class":145},[69,1943,878],{"class":94},[69,1945,1094],{"class":145},[69,1947,117],{"class":101},[69,1949,1950],{"class":71,"line":228},[69,1951,169],{"class":101},[69,1953,1954,1957,1959,1961,1963,1965,1967],{"class":71,"line":234},[69,1955,1956],{"class":183},"    off",[69,1958,421],{"class":101},[69,1960,1802],{"class":510},[69,1962,686],{"class":101},[69,1964,1807],{"class":510},[69,1966,431],{"class":101},[69,1968,105],{"class":101},[69,1970,1971,1973,1975,1977,1979,1981,1984,1986,1988,1990,1992,1994,1996],{"class":71,"line":240},[69,1972,312],{"class":138},[69,1974,95],{"class":145},[69,1976,199],{"class":90},[69,1978,1875],{"class":94},[69,1980,205],{"class":145},[69,1982,1983],{"class":90},"delete",[69,1985,982],{"class":282},[69,1987,415],{"class":101},[69,1989,1783],{"class":94},[69,1991,1244],{"class":145},[69,1993,1802],{"class":94},[69,1995,1267],{"class":145},[69,1997,117],{"class":101},[69,1999,2000,2003,2005,2007,2009,2011,2013,2015,2017,2019,2021,2023,2025,2027,2029,2032,2035,2037,2039,2041,2043,2046,2048,2050],{"class":71,"line":251},[69,2001,2002],{"class":138},"        else",[69,2004,982],{"class":282},[69,2006,415],{"class":101},[69,2008,1783],{"class":94},[69,2010,1244],{"class":145},[69,2012,1802],{"class":94},[69,2014,1254],{"class":145},[69,2016,279],{"class":90},[69,2018,982],{"class":282},[69,2020,415],{"class":101},[69,2022,1783],{"class":94},[69,2024,1244],{"class":145},[69,2026,1802],{"class":94},[69,2028,1267],{"class":145},[69,2030,2031],{"class":101},"?.",[69,2033,2034],{"class":126},"filter",[69,2036,421],{"class":145},[69,2038,1933],{"class":510},[69,2040,1936],{"class":82},[69,2042,1939],{"class":94},[69,2044,2045],{"class":90}," !==",[69,2047,1807],{"class":94},[69,2049,431],{"class":145},[69,2051,117],{"class":101},[69,2053,2054],{"class":71,"line":258},[69,2055,169],{"class":101},[69,2057,2058],{"class":71,"line":264},[69,2059,442],{"class":101},[69,2061,2062,2064,2067,2069,2071,2073,2075],{"class":71,"line":270},[69,2063,83],{"class":82},[69,2065,2066],{"class":86}," bus",[69,2068,91],{"class":90},[69,2070,552],{"class":90},[69,2072,1764],{"class":126},[69,2074,130],{"class":94},[69,2076,117],{"class":101},[69,2078,2079,2082,2084,2087,2089,2091,2094,2096,2098,2101,2103,2106,2108,2110,2112,2115,2118,2120,2123,2125,2127],{"class":71,"line":288},[69,2080,2081],{"class":94},"bus",[69,2083,415],{"class":101},[69,2085,2086],{"class":126},"on",[69,2088,421],{"class":94},[69,2090,160],{"class":152},[69,2092,2093],{"class":156},"userLogin",[69,2095,160],{"class":152},[69,2097,686],{"class":101},[69,2099,2100],{"class":510}," user",[69,2102,1936],{"class":82},[69,2104,2105],{"class":94}," console",[69,2107,415],{"class":101},[69,2109,418],{"class":126},[69,2111,421],{"class":94},[69,2113,2114],{"class":152},"`${",[69,2116,2117],{"class":94},"user",[69,2119,243],{"class":152},[69,2121,2122],{"class":156}," logged in",[69,2124,766],{"class":152},[69,2126,1094],{"class":94},[69,2128,117],{"class":101},[69,2130,2131,2133,2135,2138,2140,2142,2144,2146,2148,2150,2152,2154,2156],{"class":71,"line":299},[69,2132,2081],{"class":94},[69,2134,415],{"class":101},[69,2136,2137],{"class":126},"emit",[69,2139,421],{"class":94},[69,2141,160],{"class":152},[69,2143,2093],{"class":156},[69,2145,160],{"class":152},[69,2147,686],{"class":101},[69,2149,153],{"class":152},[69,2151,810],{"class":156},[69,2153,160],{"class":152},[69,2155,431],{"class":94},[69,2157,117],{"class":101},[23,2159,2160,2162,2163,2166],{},[48,2161,366],{},"：跨组件通信（Vue 的 ",[66,2164,2165],{},"EventBus","）、微前端通信、全局消息通知。",[33,2168,2170],{"id":2169},"三行为型模式","三、行为型模式",[23,2172,2173],{},"行为型模式关注对象之间的通信和职责分配。",[41,2175,2177],{"id":2176},"_1-观察者模式observer","1. 观察者模式（Observer）",[23,2179,2180,2182,2183,2186],{},[48,2181,50],{},"：定义对象间的一对多依赖关系，当一个对象状态改变时，所有依赖它的对象都会收到通知。它与发布-订阅的区别：观察者模式中",[48,2184,2185],{},"观察者直接注册在被观察者上","，没有中央调度器。",[23,2188,2189,382],{},[48,2190,2191,2192,2195],{},"使用 ",[66,2193,2194],{},"EventTarget"," 实现",[59,2197,2199],{"className":61,"code":2198,"language":63,"meta":64,"style":64},"class Subject extends EventTarget {\n    setState(value) {\n        this.state = value;\n        this.dispatchEvent(new CustomEvent(\"change\", { detail: value }));\n    }\n}\nconst sub = new Subject();\nsub.addEventListener(\"change\", e => console.log(\"Observer 1:\", e.detail));\nsub.addEventListener(\"change\", e => console.log(\"Observer 2:\", e.detail));\nsub.setState(42);\n",[66,2200,2201,2216,2230,2245,2289,2293,2297,2314,2365,2412],{"__ignoreMap":64},[69,2202,2203,2205,2208,2211,2214],{"class":71,"line":72},[69,2204,392],{"class":82},[69,2206,2207],{"class":395}," Subject",[69,2209,2210],{"class":82}," extends",[69,2212,2213],{"class":395}," EventTarget",[69,2215,105],{"class":101},[69,2217,2218,2221,2223,2226,2228],{"class":71,"line":79},[69,2219,2220],{"class":183},"    setState",[69,2222,421],{"class":101},[69,2224,2225],{"class":510},"value",[69,2227,431],{"class":101},[69,2229,105],{"class":101},[69,2231,2232,2234,2236,2239,2241,2243],{"class":71,"line":108},[69,2233,941],{"class":282},[69,2235,415],{"class":101},[69,2237,2238],{"class":94},"state",[69,2240,91],{"class":90},[69,2242,1579],{"class":94},[69,2244,117],{"class":101},[69,2246,2247,2249,2251,2254,2256,2259,2262,2264,2266,2269,2271,2273,2275,2278,2280,2282,2285,2287],{"class":71,"line":120},[69,2248,941],{"class":282},[69,2250,415],{"class":101},[69,2252,2253],{"class":126},"dispatchEvent",[69,2255,421],{"class":145},[69,2257,2258],{"class":90},"new",[69,2260,2261],{"class":126}," CustomEvent",[69,2263,421],{"class":145},[69,2265,160],{"class":152},[69,2267,2268],{"class":156},"change",[69,2270,160],{"class":152},[69,2272,686],{"class":101},[69,2274,142],{"class":101},[69,2276,2277],{"class":145}," detail",[69,2279,149],{"class":101},[69,2281,1579],{"class":94},[69,2283,2284],{"class":101}," }",[69,2286,1094],{"class":145},[69,2288,117],{"class":101},[69,2290,2291],{"class":71,"line":135},[69,2292,169],{"class":101},[69,2294,2295],{"class":71,"line":166},[69,2296,442],{"class":101},[69,2298,2299,2301,2304,2306,2308,2310,2312],{"class":71,"line":172},[69,2300,83],{"class":82},[69,2302,2303],{"class":86}," sub",[69,2305,91],{"class":90},[69,2307,552],{"class":90},[69,2309,2207],{"class":126},[69,2311,130],{"class":94},[69,2313,117],{"class":101},[69,2315,2316,2319,2321,2324,2326,2328,2330,2332,2334,2337,2339,2341,2343,2345,2347,2349,2352,2354,2356,2358,2360,2363],{"class":71,"line":180},[69,2317,2318],{"class":94},"sub",[69,2320,415],{"class":101},[69,2322,2323],{"class":126},"addEventListener",[69,2325,421],{"class":94},[69,2327,160],{"class":152},[69,2329,2268],{"class":156},[69,2331,160],{"class":152},[69,2333,686],{"class":101},[69,2335,2336],{"class":510}," e",[69,2338,1936],{"class":82},[69,2340,2105],{"class":94},[69,2342,415],{"class":101},[69,2344,418],{"class":126},[69,2346,421],{"class":94},[69,2348,160],{"class":152},[69,2350,2351],{"class":156},"Observer 1:",[69,2353,160],{"class":152},[69,2355,686],{"class":101},[69,2357,2336],{"class":94},[69,2359,415],{"class":101},[69,2361,2362],{"class":94},"detail))",[69,2364,117],{"class":101},[69,2366,2367,2369,2371,2373,2375,2377,2379,2381,2383,2385,2387,2389,2391,2393,2395,2397,2400,2402,2404,2406,2408,2410],{"class":71,"line":191},[69,2368,2318],{"class":94},[69,2370,415],{"class":101},[69,2372,2323],{"class":126},[69,2374,421],{"class":94},[69,2376,160],{"class":152},[69,2378,2268],{"class":156},[69,2380,160],{"class":152},[69,2382,686],{"class":101},[69,2384,2336],{"class":510},[69,2386,1936],{"class":82},[69,2388,2105],{"class":94},[69,2390,415],{"class":101},[69,2392,418],{"class":126},[69,2394,421],{"class":94},[69,2396,160],{"class":152},[69,2398,2399],{"class":156},"Observer 2:",[69,2401,160],{"class":152},[69,2403,686],{"class":101},[69,2405,2336],{"class":94},[69,2407,415],{"class":101},[69,2409,2362],{"class":94},[69,2411,117],{"class":101},[69,2413,2414,2416,2418,2421,2423,2426,2428],{"class":71,"line":218},[69,2415,2318],{"class":94},[69,2417,415],{"class":101},[69,2419,2420],{"class":126},"setState",[69,2422,421],{"class":94},[69,2424,2425],{"class":817},"42",[69,2427,431],{"class":94},[69,2429,117],{"class":101},[23,2431,2432,2434],{},[48,2433,366],{},"：DOM 事件监听、响应式数据绑定（如 MobX）。",[41,2436,2438],{"id":2437},"_2-策略模式strategy","2. 策略模式（Strategy）",[23,2440,2441,2443],{},[48,2442,50],{},"：定义一系列算法，把它们封装起来，并使它们可以相互替换。算法的变化独立于使用它的客户端。",[59,2445,2447],{"className":61,"code":2446,"language":63,"meta":64,"style":64},"\u002F\u002F 策略集\nconst strategies = {\n    plus: (a, b) => a + b,\n    minus: (a, b) => a - b,\n    multiply: (a, b) => a * b,\n};\nfunction execute(operation, a, b) {\n    return strategies[operation](a, b);\n}\nconsole.log(execute(\"plus\", 5, 3)); \u002F\u002F 8\n",[66,2448,2449,2454,2465,2495,2523,2551,2555,2580,2603,2607],{"__ignoreMap":64},[69,2450,2451],{"class":71,"line":72},[69,2452,2453],{"class":75},"\u002F\u002F 策略集\n",[69,2455,2456,2458,2461,2463],{"class":71,"line":79},[69,2457,83],{"class":82},[69,2459,2460],{"class":86}," strategies",[69,2462,91],{"class":90},[69,2464,105],{"class":101},[69,2466,2467,2470,2472,2474,2476,2478,2481,2483,2485,2488,2490,2492],{"class":71,"line":108},[69,2468,2469],{"class":126},"    plus",[69,2471,149],{"class":101},[69,2473,95],{"class":101},[69,2475,27],{"class":510},[69,2477,686],{"class":101},[69,2479,2480],{"class":510}," b",[69,2482,431],{"class":101},[69,2484,1936],{"class":82},[69,2486,2487],{"class":94}," a ",[69,2489,1534],{"class":90},[69,2491,2480],{"class":94},[69,2493,2494],{"class":101},",\n",[69,2496,2497,2500,2502,2504,2506,2508,2510,2512,2514,2516,2519,2521],{"class":71,"line":120},[69,2498,2499],{"class":126},"    minus",[69,2501,149],{"class":101},[69,2503,95],{"class":101},[69,2505,27],{"class":510},[69,2507,686],{"class":101},[69,2509,2480],{"class":510},[69,2511,431],{"class":101},[69,2513,1936],{"class":82},[69,2515,2487],{"class":94},[69,2517,2518],{"class":90},"-",[69,2520,2480],{"class":94},[69,2522,2494],{"class":101},[69,2524,2525,2528,2530,2532,2534,2536,2538,2540,2542,2544,2547,2549],{"class":71,"line":135},[69,2526,2527],{"class":126},"    multiply",[69,2529,149],{"class":101},[69,2531,95],{"class":101},[69,2533,27],{"class":510},[69,2535,686],{"class":101},[69,2537,2480],{"class":510},[69,2539,431],{"class":101},[69,2541,1936],{"class":82},[69,2543,2487],{"class":94},[69,2545,2546],{"class":90},"*",[69,2548,2480],{"class":94},[69,2550,2494],{"class":101},[69,2552,2553],{"class":71,"line":166},[69,2554,361],{"class":101},[69,2556,2557,2559,2562,2564,2567,2569,2572,2574,2576,2578],{"class":71,"line":172},[69,2558,98],{"class":82},[69,2560,2561],{"class":126}," execute",[69,2563,421],{"class":101},[69,2565,2566],{"class":510},"operation",[69,2568,686],{"class":101},[69,2570,2571],{"class":510}," a",[69,2573,686],{"class":101},[69,2575,2480],{"class":510},[69,2577,431],{"class":101},[69,2579,105],{"class":101},[69,2581,2582,2584,2586,2588,2590,2593,2595,2597,2599,2601],{"class":71,"line":180},[69,2583,175],{"class":138},[69,2585,2460],{"class":94},[69,2587,1244],{"class":145},[69,2589,2566],{"class":94},[69,2591,2592],{"class":145},"](",[69,2594,27],{"class":94},[69,2596,686],{"class":101},[69,2598,2480],{"class":94},[69,2600,431],{"class":145},[69,2602,117],{"class":101},[69,2604,2605],{"class":71,"line":191},[69,2606,442],{"class":101},[69,2608,2609,2611,2613,2615,2617,2620,2622,2624,2627,2629,2631,2634,2636,2639,2641,2643],{"class":71,"line":218},[69,2610,1070],{"class":94},[69,2612,415],{"class":101},[69,2614,418],{"class":126},[69,2616,421],{"class":94},[69,2618,2619],{"class":126},"execute",[69,2621,421],{"class":94},[69,2623,160],{"class":152},[69,2625,2626],{"class":156},"plus",[69,2628,160],{"class":152},[69,2630,686],{"class":101},[69,2632,2633],{"class":817}," 5",[69,2635,686],{"class":101},[69,2637,2638],{"class":817}," 3",[69,2640,1094],{"class":94},[69,2642,1097],{"class":101},[69,2644,2645],{"class":75}," \u002F\u002F 8\n",[23,2647,2648,2650],{},[48,2649,366],{},"：表单验证规则、动画缓动算法、路由匹配策略。",[41,2652,2654],{"id":2653},"_3-迭代器模式iterator","3. 迭代器模式（Iterator）",[23,2656,2657,2659,2660,2663],{},[48,2658,50],{},"：提供一种方法顺序访问聚合对象中的各个元素，而不暴露其内部表示。JavaScript 内置了迭代器协议（",[66,2661,2662],{},"Symbol.iterator","）。",[59,2665,2667],{"className":61,"code":2666,"language":63,"meta":64,"style":64},"\u002F\u002F 自定义可迭代对象\nconst myCollection = {\n    items: [1, 2, 3],\n    [Symbol.iterator]() {\n        let index = 0;\n        return {\n            next: () => ({\n                value: this.items[index],\n                done: index++ >= this.items.length,\n            }),\n        };\n    },\n};\nfor (const val of myCollection) console.log(val); \u002F\u002F 1,2,3\n",[66,2668,2669,2674,2685,2710,2724,2738,2744,2759,2782,2810,2819,2824,2828,2832],{"__ignoreMap":64},[69,2670,2671],{"class":71,"line":72},[69,2672,2673],{"class":75},"\u002F\u002F 自定义可迭代对象\n",[69,2675,2676,2678,2681,2683],{"class":71,"line":79},[69,2677,83],{"class":82},[69,2679,2680],{"class":86}," myCollection",[69,2682,91],{"class":90},[69,2684,105],{"class":101},[69,2686,2687,2690,2692,2695,2697,2699,2702,2704,2706,2708],{"class":71,"line":108},[69,2688,2689],{"class":145},"    items",[69,2691,149],{"class":101},[69,2693,2694],{"class":94}," [",[69,2696,1729],{"class":817},[69,2698,686],{"class":101},[69,2700,2701],{"class":817}," 2",[69,2703,686],{"class":101},[69,2705,2638],{"class":817},[69,2707,1267],{"class":94},[69,2709,2494],{"class":101},[69,2711,2712,2715,2717,2720,2722],{"class":71,"line":120},[69,2713,2714],{"class":94},"    [Symbol",[69,2716,415],{"class":101},[69,2718,2719],{"class":94},"iterator]",[69,2721,130],{"class":101},[69,2723,105],{"class":101},[69,2725,2726,2729,2732,2734,2736],{"class":71,"line":135},[69,2727,2728],{"class":82},"        let",[69,2730,2731],{"class":94}," index",[69,2733,91],{"class":90},[69,2735,1609],{"class":817},[69,2737,117],{"class":101},[69,2739,2740,2742],{"class":71,"line":166},[69,2741,139],{"class":138},[69,2743,105],{"class":101},[69,2745,2746,2749,2751,2753,2755,2757],{"class":71,"line":172},[69,2747,2748],{"class":126},"            next",[69,2750,149],{"class":101},[69,2752,102],{"class":101},[69,2754,1936],{"class":82},[69,2756,95],{"class":145},[69,2758,529],{"class":101},[69,2760,2761,2764,2766,2768,2770,2773,2775,2778,2780],{"class":71,"line":180},[69,2762,2763],{"class":145},"                value",[69,2765,149],{"class":101},[69,2767,982],{"class":282},[69,2769,415],{"class":101},[69,2771,2772],{"class":94},"items",[69,2774,1244],{"class":145},[69,2776,2777],{"class":94},"index",[69,2779,1267],{"class":145},[69,2781,2494],{"class":101},[69,2783,2784,2787,2789,2791,2794,2797,2799,2801,2803,2805,2808],{"class":71,"line":191},[69,2785,2786],{"class":145},"                done",[69,2788,149],{"class":101},[69,2790,2731],{"class":94},[69,2792,2793],{"class":90},"++",[69,2795,2796],{"class":90}," >=",[69,2798,982],{"class":282},[69,2800,415],{"class":101},[69,2802,2772],{"class":94},[69,2804,415],{"class":101},[69,2806,2807],{"class":86},"length",[69,2809,2494],{"class":101},[69,2811,2812,2815,2817],{"class":71,"line":218},[69,2813,2814],{"class":101},"            }",[69,2816,431],{"class":145},[69,2818,2494],{"class":101},[69,2820,2821],{"class":71,"line":228},[69,2822,2823],{"class":101},"        };\n",[69,2825,2826],{"class":71,"line":234},[69,2827,355],{"class":101},[69,2829,2830],{"class":71,"line":240},[69,2831,361],{"class":101},[69,2833,2834,2837,2839,2841,2844,2847,2850,2852,2854,2857,2859],{"class":71,"line":251},[69,2835,2836],{"class":138},"for",[69,2838,95],{"class":94},[69,2840,83],{"class":82},[69,2842,2843],{"class":86}," val",[69,2845,2846],{"class":90}," of",[69,2848,2849],{"class":94}," myCollection) console",[69,2851,415],{"class":101},[69,2853,418],{"class":126},[69,2855,2856],{"class":94},"(val)",[69,2858,1097],{"class":101},[69,2860,2861],{"class":75}," \u002F\u002F 1,2,3\n",[23,2863,2864,2866,2867,2870],{},[48,2865,366],{},"：遍历自定义数据结构、实现 ",[66,2868,2869],{},"for...of"," 兼容性、分页数据迭代器。",[41,2872,2874],{"id":2873},"_4-命令模式command","4. 命令模式（Command）",[23,2876,2877,2879],{},[48,2878,50],{},"：将请求封装成对象，从而使您可以用不同的请求对客户进行参数化、排队或记录日志，以及支持可撤销操作。",[59,2881,2883],{"className":61,"code":2882,"language":63,"meta":64,"style":64},"class Command {\n    constructor(receiver, action) {\n        this.receiver = receiver;\n        this.action = action;\n    }\n    execute() {\n        this.receiver[this.action]();\n    }\n}\nclass TV {\n    on() {\n        console.log(\"TV on\");\n    }\n    off() {\n        console.log(\"TV off\");\n    }\n}\nconst tv = new TV();\nconst onCommand = new Command(tv, \"on\");\nconst offCommand = new Command(tv, \"off\");\nonCommand.execute(); \u002F\u002F TV on\n",[66,2884,2885,2894,2912,2927,2942,2946,2955,2976,2980,2984,2993,3001,3022,3026,3034,3055,3059,3063,3080,3108,3136],{"__ignoreMap":64},[69,2886,2887,2889,2892],{"class":71,"line":72},[69,2888,392],{"class":82},[69,2890,2891],{"class":395}," Command",[69,2893,105],{"class":101},[69,2895,2896,2898,2900,2903,2905,2908,2910],{"class":71,"line":79},[69,2897,927],{"class":82},[69,2899,421],{"class":101},[69,2901,2902],{"class":510},"receiver",[69,2904,686],{"class":101},[69,2906,2907],{"class":510}," action",[69,2909,431],{"class":101},[69,2911,105],{"class":101},[69,2913,2914,2916,2918,2920,2922,2925],{"class":71,"line":108},[69,2915,941],{"class":282},[69,2917,415],{"class":101},[69,2919,2902],{"class":94},[69,2921,91],{"class":90},[69,2923,2924],{"class":94}," receiver",[69,2926,117],{"class":101},[69,2928,2929,2931,2933,2936,2938,2940],{"class":71,"line":120},[69,2930,941],{"class":282},[69,2932,415],{"class":101},[69,2934,2935],{"class":94},"action",[69,2937,91],{"class":90},[69,2939,2907],{"class":94},[69,2941,117],{"class":101},[69,2943,2944],{"class":71,"line":135},[69,2945,169],{"class":101},[69,2947,2948,2951,2953],{"class":71,"line":166},[69,2949,2950],{"class":183},"    execute",[69,2952,130],{"class":101},[69,2954,105],{"class":101},[69,2956,2957,2959,2961,2963,2965,2967,2969,2971,2974],{"class":71,"line":172},[69,2958,941],{"class":282},[69,2960,415],{"class":101},[69,2962,2902],{"class":94},[69,2964,1244],{"class":145},[69,2966,775],{"class":282},[69,2968,415],{"class":101},[69,2970,2935],{"class":94},[69,2972,2973],{"class":145},"]()",[69,2975,117],{"class":101},[69,2977,2978],{"class":71,"line":180},[69,2979,169],{"class":101},[69,2981,2982],{"class":71,"line":191},[69,2983,442],{"class":101},[69,2985,2986,2988,2991],{"class":71,"line":218},[69,2987,392],{"class":82},[69,2989,2990],{"class":395}," TV",[69,2992,105],{"class":101},[69,2994,2995,2997,2999],{"class":71,"line":228},[69,2996,1797],{"class":183},[69,2998,130],{"class":101},[69,3000,105],{"class":101},[69,3002,3003,3005,3007,3009,3011,3013,3016,3018,3020],{"class":71,"line":234},[69,3004,412],{"class":94},[69,3006,415],{"class":101},[69,3008,418],{"class":126},[69,3010,421],{"class":145},[69,3012,160],{"class":152},[69,3014,3015],{"class":156},"TV on",[69,3017,160],{"class":152},[69,3019,431],{"class":145},[69,3021,117],{"class":101},[69,3023,3024],{"class":71,"line":240},[69,3025,169],{"class":101},[69,3027,3028,3030,3032],{"class":71,"line":251},[69,3029,1956],{"class":183},[69,3031,130],{"class":101},[69,3033,105],{"class":101},[69,3035,3036,3038,3040,3042,3044,3046,3049,3051,3053],{"class":71,"line":258},[69,3037,412],{"class":94},[69,3039,415],{"class":101},[69,3041,418],{"class":126},[69,3043,421],{"class":145},[69,3045,160],{"class":152},[69,3047,3048],{"class":156},"TV off",[69,3050,160],{"class":152},[69,3052,431],{"class":145},[69,3054,117],{"class":101},[69,3056,3057],{"class":71,"line":264},[69,3058,169],{"class":101},[69,3060,3061],{"class":71,"line":270},[69,3062,442],{"class":101},[69,3064,3065,3067,3070,3072,3074,3076,3078],{"class":71,"line":288},[69,3066,83],{"class":82},[69,3068,3069],{"class":86}," tv",[69,3071,91],{"class":90},[69,3073,552],{"class":90},[69,3075,2990],{"class":126},[69,3077,130],{"class":94},[69,3079,117],{"class":101},[69,3081,3082,3084,3087,3089,3091,3093,3096,3098,3100,3102,3104,3106],{"class":71,"line":299},[69,3083,83],{"class":82},[69,3085,3086],{"class":86}," onCommand",[69,3088,91],{"class":90},[69,3090,552],{"class":90},[69,3092,2891],{"class":126},[69,3094,3095],{"class":94},"(tv",[69,3097,686],{"class":101},[69,3099,153],{"class":152},[69,3101,2086],{"class":156},[69,3103,160],{"class":152},[69,3105,431],{"class":94},[69,3107,117],{"class":101},[69,3109,3110,3112,3115,3117,3119,3121,3123,3125,3127,3130,3132,3134],{"class":71,"line":309},[69,3111,83],{"class":82},[69,3113,3114],{"class":86}," offCommand",[69,3116,91],{"class":90},[69,3118,552],{"class":90},[69,3120,2891],{"class":126},[69,3122,3095],{"class":94},[69,3124,686],{"class":101},[69,3126,153],{"class":152},[69,3128,3129],{"class":156},"off",[69,3131,160],{"class":152},[69,3133,431],{"class":94},[69,3135,117],{"class":101},[69,3137,3138,3141,3143,3145,3147,3149],{"class":71,"line":343},[69,3139,3140],{"class":94},"onCommand",[69,3142,415],{"class":101},[69,3144,2619],{"class":126},[69,3146,130],{"class":94},[69,3148,1097],{"class":101},[69,3150,3151],{"class":75}," \u002F\u002F TV on\n",[23,3153,3154,3156],{},[48,3155,366],{},"：撤销\u002F重做（如编辑器）、事务操作、宏命令。",[41,3158,3160],{"id":3159},"_5-职责链模式chain-of-responsibility","5. 职责链模式（Chain of Responsibility）",[23,3162,3163,3165],{},[48,3164,50],{},"：使多个对象都有机会处理请求，将这些对象连成一条链，并沿着链传递请求，直到有一个对象处理它为止。",[59,3167,3169],{"className":61,"code":3168,"language":63,"meta":64,"style":64},"class Handler {\n    setNext(handler) {\n        this.next = handler;\n        return handler;\n    }\n    handle(request) {\n        if (this.canHandle(request)) return this.process(request);\n        if (this.next) return this.next.handle(request);\n        return \"No handler found\";\n    }\n}\nclass AuthHandler extends Handler {\n    canHandle(req) {\n        return req.needAuth;\n    }\n    process(req) {\n        return \"Authenticated\";\n    }\n}\nclass LoggerHandler extends Handler {\n    canHandle(req) {\n        return true;\n    }\n    process(req) {\n        console.log(\"Log request\");\n        return this.next?.handle(req);\n    }\n}\n\u002F\u002F 使用\nconst auth = new AuthHandler();\nconst logger = new LoggerHandler();\nauth.setNext(logger);\nauth.handle({ needAuth: true });\n",[66,3170,3171,3180,3194,3209,3217,3221,3234,3271,3306,3319,3323,3327,3340,3354,3368,3372,3385,3398,3402,3406,3419,3431,3439,3443,3456,3478,3501,3506,3511,3516,3534,3552,3568],{"__ignoreMap":64},[69,3172,3173,3175,3178],{"class":71,"line":72},[69,3174,392],{"class":82},[69,3176,3177],{"class":395}," Handler",[69,3179,105],{"class":101},[69,3181,3182,3185,3187,3190,3192],{"class":71,"line":79},[69,3183,3184],{"class":183},"    setNext",[69,3186,421],{"class":101},[69,3188,3189],{"class":510},"handler",[69,3191,431],{"class":101},[69,3193,105],{"class":101},[69,3195,3196,3198,3200,3203,3205,3207],{"class":71,"line":108},[69,3197,941],{"class":282},[69,3199,415],{"class":101},[69,3201,3202],{"class":94},"next",[69,3204,91],{"class":90},[69,3206,1477],{"class":94},[69,3208,117],{"class":101},[69,3210,3211,3213,3215],{"class":71,"line":120},[69,3212,139],{"class":138},[69,3214,1477],{"class":94},[69,3216,117],{"class":101},[69,3218,3219],{"class":71,"line":135},[69,3220,169],{"class":101},[69,3222,3223,3226,3228,3230,3232],{"class":71,"line":166},[69,3224,3225],{"class":183},"    handle",[69,3227,421],{"class":101},[69,3229,991],{"class":510},[69,3231,431],{"class":101},[69,3233,105],{"class":101},[69,3235,3236,3238,3240,3242,3244,3247,3249,3251,3254,3256,3258,3260,3263,3265,3267,3269],{"class":71,"line":172},[69,3237,312],{"class":138},[69,3239,95],{"class":145},[69,3241,775],{"class":282},[69,3243,415],{"class":101},[69,3245,3246],{"class":126},"canHandle",[69,3248,421],{"class":145},[69,3250,991],{"class":94},[69,3252,3253],{"class":145},")) ",[69,3255,1382],{"class":138},[69,3257,982],{"class":282},[69,3259,415],{"class":101},[69,3261,3262],{"class":126},"process",[69,3264,421],{"class":145},[69,3266,991],{"class":94},[69,3268,431],{"class":145},[69,3270,117],{"class":101},[69,3272,3273,3275,3277,3279,3281,3283,3285,3287,3289,3291,3293,3295,3298,3300,3302,3304],{"class":71,"line":180},[69,3274,312],{"class":138},[69,3276,95],{"class":145},[69,3278,775],{"class":282},[69,3280,415],{"class":101},[69,3282,3202],{"class":94},[69,3284,205],{"class":145},[69,3286,1382],{"class":138},[69,3288,982],{"class":282},[69,3290,415],{"class":101},[69,3292,3202],{"class":94},[69,3294,415],{"class":101},[69,3296,3297],{"class":126},"handle",[69,3299,421],{"class":145},[69,3301,991],{"class":94},[69,3303,431],{"class":145},[69,3305,117],{"class":101},[69,3307,3308,3310,3312,3315,3317],{"class":71,"line":191},[69,3309,139],{"class":138},[69,3311,153],{"class":152},[69,3313,3314],{"class":156},"No handler found",[69,3316,160],{"class":152},[69,3318,117],{"class":101},[69,3320,3321],{"class":71,"line":218},[69,3322,169],{"class":101},[69,3324,3325],{"class":71,"line":228},[69,3326,442],{"class":101},[69,3328,3329,3331,3334,3336,3338],{"class":71,"line":234},[69,3330,392],{"class":82},[69,3332,3333],{"class":395}," AuthHandler",[69,3335,2210],{"class":82},[69,3337,3177],{"class":395},[69,3339,105],{"class":101},[69,3341,3342,3345,3347,3350,3352],{"class":71,"line":240},[69,3343,3344],{"class":183},"    canHandle",[69,3346,421],{"class":101},[69,3348,3349],{"class":510},"req",[69,3351,431],{"class":101},[69,3353,105],{"class":101},[69,3355,3356,3358,3361,3363,3366],{"class":71,"line":251},[69,3357,139],{"class":138},[69,3359,3360],{"class":94}," req",[69,3362,415],{"class":101},[69,3364,3365],{"class":94},"needAuth",[69,3367,117],{"class":101},[69,3369,3370],{"class":71,"line":258},[69,3371,169],{"class":101},[69,3373,3374,3377,3379,3381,3383],{"class":71,"line":264},[69,3375,3376],{"class":183},"    process",[69,3378,421],{"class":101},[69,3380,3349],{"class":510},[69,3382,431],{"class":101},[69,3384,105],{"class":101},[69,3386,3387,3389,3391,3394,3396],{"class":71,"line":270},[69,3388,139],{"class":138},[69,3390,153],{"class":152},[69,3392,3393],{"class":156},"Authenticated",[69,3395,160],{"class":152},[69,3397,117],{"class":101},[69,3399,3400],{"class":71,"line":288},[69,3401,169],{"class":101},[69,3403,3404],{"class":71,"line":299},[69,3405,442],{"class":101},[69,3407,3408,3410,3413,3415,3417],{"class":71,"line":309},[69,3409,392],{"class":82},[69,3411,3412],{"class":395}," LoggerHandler",[69,3414,2210],{"class":82},[69,3416,3177],{"class":395},[69,3418,105],{"class":101},[69,3420,3421,3423,3425,3427,3429],{"class":71,"line":343},[69,3422,3344],{"class":183},[69,3424,421],{"class":101},[69,3426,3349],{"class":510},[69,3428,431],{"class":101},[69,3430,105],{"class":101},[69,3432,3433,3435,3437],{"class":71,"line":352},[69,3434,139],{"class":138},[69,3436,1656],{"class":1655},[69,3438,117],{"class":101},[69,3440,3441],{"class":71,"line":358},[69,3442,169],{"class":101},[69,3444,3446,3448,3450,3452,3454],{"class":71,"line":3445},24,[69,3447,3376],{"class":183},[69,3449,421],{"class":101},[69,3451,3349],{"class":510},[69,3453,431],{"class":101},[69,3455,105],{"class":101},[69,3457,3459,3461,3463,3465,3467,3469,3472,3474,3476],{"class":71,"line":3458},25,[69,3460,412],{"class":94},[69,3462,415],{"class":101},[69,3464,418],{"class":126},[69,3466,421],{"class":145},[69,3468,160],{"class":152},[69,3470,3471],{"class":156},"Log request",[69,3473,160],{"class":152},[69,3475,431],{"class":145},[69,3477,117],{"class":101},[69,3479,3481,3483,3485,3487,3489,3491,3493,3495,3497,3499],{"class":71,"line":3480},26,[69,3482,139],{"class":138},[69,3484,982],{"class":282},[69,3486,415],{"class":101},[69,3488,3202],{"class":94},[69,3490,2031],{"class":101},[69,3492,3297],{"class":126},[69,3494,421],{"class":145},[69,3496,3349],{"class":94},[69,3498,431],{"class":145},[69,3500,117],{"class":101},[69,3502,3504],{"class":71,"line":3503},27,[69,3505,169],{"class":101},[69,3507,3509],{"class":71,"line":3508},28,[69,3510,442],{"class":101},[69,3512,3514],{"class":71,"line":3513},29,[69,3515,1030],{"class":75},[69,3517,3519,3521,3524,3526,3528,3530,3532],{"class":71,"line":3518},30,[69,3520,83],{"class":82},[69,3522,3523],{"class":86}," auth",[69,3525,91],{"class":90},[69,3527,552],{"class":90},[69,3529,3333],{"class":126},[69,3531,130],{"class":94},[69,3533,117],{"class":101},[69,3535,3537,3539,3542,3544,3546,3548,3550],{"class":71,"line":3536},31,[69,3538,83],{"class":82},[69,3540,3541],{"class":86}," logger",[69,3543,91],{"class":90},[69,3545,552],{"class":90},[69,3547,3412],{"class":126},[69,3549,130],{"class":94},[69,3551,117],{"class":101},[69,3553,3555,3558,3560,3563,3566],{"class":71,"line":3554},32,[69,3556,3557],{"class":94},"auth",[69,3559,415],{"class":101},[69,3561,3562],{"class":126},"setNext",[69,3564,3565],{"class":94},"(logger)",[69,3567,117],{"class":101},[69,3569,3571,3573,3575,3577,3579,3582,3585,3587,3589,3591,3593],{"class":71,"line":3570},33,[69,3572,3557],{"class":94},[69,3574,415],{"class":101},[69,3576,3297],{"class":126},[69,3578,421],{"class":94},[69,3580,3581],{"class":101},"{",[69,3583,3584],{"class":145}," needAuth",[69,3586,149],{"class":101},[69,3588,1656],{"class":1655},[69,3590,2284],{"class":101},[69,3592,431],{"class":94},[69,3594,117],{"class":101},[23,3596,3597,3599],{},[48,3598,366],{},"：中间件（Express\u002FKoa 中间件链条）、表单校验预处理、权限校验升级链。",[33,3601,3602],{"id":3602},"总结对比",[3604,3605,3606,3625],"table",{},[3607,3608,3609],"thead",{},[3610,3611,3612,3616,3619,3622],"tr",{},[3613,3614,3615],"th",{},"分类",[3613,3617,3618],{},"模式",[3613,3620,3621],{},"核心特点",[3613,3623,3624],{},"前端典型应用",[3626,3627,3628,3643,3656,3669,3683,3696,3709,3722,3736,3749,3765,3778],"tbody",{},[3610,3629,3630,3634,3637,3640],{},[3631,3632,3633],"td",{},"创建型",[3631,3635,3636],{},"单例",[3631,3638,3639],{},"全局唯一实例",[3631,3641,3642],{},"Store、全局弹窗管理器",[3610,3644,3645,3647,3650,3653],{},[3631,3646],{},[3631,3648,3649],{},"工厂",[3631,3651,3652],{},"封装对象创建逻辑",[3631,3654,3655],{},"动态组件创建、API 服务生成",[3610,3657,3658,3660,3663,3666],{},[3631,3659],{},[3631,3661,3662],{},"构造函数+原型",[3631,3664,3665],{},"JS 原生对象创建模式",[3631,3667,3668],{},"所有基于 class\u002F构造函数的对象",[3610,3670,3671,3674,3677,3680],{},[3631,3672,3673],{},"结构型",[3631,3675,3676],{},"适配器",[3631,3678,3679],{},"接口转换，兼容旧代码",[3631,3681,3682],{},"封装不同浏览器 API、第三方库适配",[3610,3684,3685,3687,3690,3693],{},[3631,3686],{},[3631,3688,3689],{},"装饰器（HOC）",[3631,3691,3692],{},"动态增强功能",[3631,3694,3695],{},"React HOC、日志\u002F性能装饰器",[3610,3697,3698,3700,3703,3706],{},[3631,3699],{},[3631,3701,3702],{},"代理（Proxy）",[3631,3704,3705],{},"控制访问，Vue 响应式核心",[3631,3707,3708],{},"数据劫持、图片懒加载代理",[3610,3710,3711,3713,3716,3719],{},[3631,3712],{},[3631,3714,3715],{},"发布-订阅（事件总线）",[3631,3717,3718],{},"通过事件中心解耦发布者和订阅者",[3631,3720,3721],{},"跨组件通信、全局事件通知",[3610,3723,3724,3727,3730,3733],{},[3631,3725,3726],{},"行为型",[3631,3728,3729],{},"观察者（EventTarget）",[3631,3731,3732],{},"目标对象直接通知观察者",[3631,3734,3735],{},"DOM 事件、响应式库的内部机制",[3610,3737,3738,3740,3743,3746],{},[3631,3739],{},[3631,3741,3742],{},"策略",[3631,3744,3745],{},"算法可互换",[3631,3747,3748],{},"表单验证策略、动画算法",[3610,3750,3751,3753,3756,3759],{},[3631,3752],{},[3631,3754,3755],{},"迭代器",[3631,3757,3758],{},"统一遍历接口",[3631,3760,3761,3762,3764],{},"自定义 ",[66,3763,2869],{}," 数据结构",[3610,3766,3767,3769,3772,3775],{},[3631,3768],{},[3631,3770,3771],{},"命令",[3631,3773,3774],{},"封装请求为对象",[3631,3776,3777],{},"撤销重做、操作日志",[3610,3779,3780,3782,3785,3788],{},[3631,3781],{},[3631,3783,3784],{},"职责链",[3631,3786,3787],{},"请求沿链传递直到被处理",[3631,3789,3790],{},"Express 中间件、表单校验链",[23,3792,3793],{},"理解这些设计模式有助于阅读 Redux、Vue、Express 等库的架构；新代码应优先简单直接的模块划分，避免过度设计。",[33,3795,3796],{"id":3796},"参考文献",[23,3798,3799],{},"以下链接在编写时均可正常访问：",[3604,3801,3802,3812],{},[3607,3803,3804],{},[3610,3805,3806,3809],{},[3613,3807,3808],{},"资料",[3613,3810,3811],{},"说明",[3626,3813,3814,3827,3839],{},[3610,3815,3816,3824],{},[3631,3817,3818],{},[27,3819,3823],{"href":3820,"rel":3821},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fzh-CN\u002Fdocs\u002FWeb\u002FJavaScript\u002FGuide\u002FModules",[3822],"nofollow","MDN：模块模式",[3631,3825,3826],{},"模块与封装",[3610,3828,3829,3836],{},[3631,3830,3831],{},[27,3832,3835],{"href":3833,"rel":3834},"https:\u002F\u002Frefactoringguru.cn\u002Fdesign-patterns",[3822],"Refactoring Guru：设计模式",[3631,3837,3838],{},"模式目录（中文）",[3610,3840,3841,3848],{},[3631,3842,3843],{},[27,3844,3847],{"href":3845,"rel":3846},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fzh-CN\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FGlobal_Objects\u002FProxy",[3822],"MDN：Proxy",[3631,3849,3850],{},"代理模式实现基础",[3852,3853,3854],"style",{},"html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sfo-9, html code.shiki .sfo-9{--shiki-light:#90A4AE;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":64,"searchDepth":79,"depth":79,"links":3856},[3857,3862,3868,3875,3876],{"id":35,"depth":79,"text":36,"children":3858},[3859,3860,3861],{"id":43,"depth":108,"text":44},{"id":370,"depth":108,"text":371},{"id":662,"depth":108,"text":663},{"id":836,"depth":79,"text":837,"children":3863},[3864,3865,3866,3867],{"id":843,"depth":108,"text":844},{"id":1116,"depth":108,"text":1117},{"id":1424,"depth":108,"text":1425},{"id":1742,"depth":108,"text":1743},{"id":2169,"depth":79,"text":2170,"children":3869},[3870,3871,3872,3873,3874],{"id":2176,"depth":108,"text":2177},{"id":2437,"depth":108,"text":2438},{"id":2653,"depth":108,"text":2654},{"id":2873,"depth":108,"text":2874},{"id":3159,"depth":108,"text":3160},{"id":3602,"depth":79,"text":3602},{"id":3796,"depth":79,"text":3796},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fweb\u002FJs\u002Fdesign","knowledge\u002Fknowledge\u002Fbooklet\u002Fweb\u002FJs\u002Fdesign.md","md",{"items":3882},[3883,3887,3891,3895,3899,3903],{"path":3884,"title":3885,"description":3886,"category":10,"score":166},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Ferror","错误处理与调试","结构化错误类型、try\u002Fcatch 与全局未捕获处理是健壮应用的基础。",{"path":3888,"title":3889,"description":3890,"category":10,"score":166},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fdom-bom","浏览器相关 API","DOM 事件、存储、fetch、Worker、Observer 等由浏览器提供的 Web API（非 ECMAScript 核心）。HTML 结构见 标签。",{"path":3892,"title":3893,"description":3894,"category":10,"score":166},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fperformance","性能优化","防抖\u002F节流、渲染与内存、资源预加载及引擎行为是前端性能的主要抓手。相关 CSS 见 视觉效果、Head 资源提示。",{"path":3896,"title":3897,"description":3898,"category":10,"score":166},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fcommon","模块化与工程化","ESM、CommonJS 与打包工具（Tree Shaking、代码分割）是前端工程化的基础。入门见 JavaScript 基础 · 模块。",{"path":3900,"title":3901,"description":3902,"category":10,"score":166},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fscope","执行模型与作用域","执行上下文与词法作用域决定变量在何处可访问、闭包如何形成，以及 var \u002F let \u002F const 的差异。语言概览见 JavaScript 基础。",{"path":3904,"title":3905,"description":3906,"category":10,"score":166},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fmap-set","数据结构与集合增强","Map \u002F Set、WeakMap \u002F WeakSet、数组高阶方法、TypedArray 与 Symbol 等扩展了内置数据结构能力。见 语言基础。",{"series":3908,"title":63,"items":3909,"index":108,"prev":3949,"next":3950},"booklet\u002Fweb\u002Fjs",[3910,3914,3918,3920,3921,3923,3925,3929,3933,3935,3937,3939,3943,3947],{"path":3911,"title":3912,"date":3913,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fadvanced","函数进阶","2022-10-24",{"path":3915,"title":3916,"date":3917,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fbasics","JavaScript 基础","2023-11-24",{"path":3896,"title":3897,"date":3919,"pinned":15},"2025-06-21",{"path":7,"title":8,"date":14,"pinned":15},{"path":3888,"title":3889,"date":3922,"pinned":15},"2025-07-10",{"path":3884,"title":3885,"date":3924,"pinned":15},"2026-06-25",{"path":3926,"title":3927,"date":3928,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fevent-loop","异步编程与事件循环","2020-03-23",{"path":3930,"title":3931,"date":3932,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fexec","正则表达式","2022-05-21",{"path":3904,"title":3905,"date":3934,"pinned":15},"2024-07-10",{"path":3892,"title":3893,"date":3936,"pinned":15},"2025-07-04",{"path":29,"title":30,"date":3938,"pinned":15},"2020-04-13",{"path":3940,"title":3941,"date":3942,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fproxy","代理与反射","2022-10-23",{"path":3944,"title":3945,"date":3946,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fsafe","安全","2023-06-26",{"path":3900,"title":3901,"date":3948,"pinned":15},"2025-01-29",{"path":3896,"title":3897,"date":3919,"pinned":15},{"path":3888,"title":3889,"date":3922,"pinned":15}]