[{"data":1,"prerenderedAt":2370},["ShallowReactive",2],{"\u002Fposts\u002Fmake-your-code-more-readable":3,"surround:\u002Fposts\u002Fmake-your-code-more-readable":2364},{"id":4,"title":5,"body":6,"createdAt":2357,"description":15,"extension":2358,"meta":2359,"navigation":89,"path":2360,"seo":2361,"stem":2362,"__hash__":2363},"posts\u002Fposts\u002F2020\u002Fmake-your-code-more-readable.md","让代码更具可读性",{"type":7,"value":8,"toc":2345},"minimark",[9,12,16,21,27,32,35,121,124,198,201,242,245,254,258,261,275,361,366,510,515,625,630,698,703,786,790,793,999,1002,1006,1009,1460,1468,1472,1475,1489,1492,1496,1499,1506,1556,1559,1605,1612,1785,1788,1948,1951,1954,1958,1961,2089,2100,2111,2114,2274,2277,2281,2292,2341],[10,11,5],"h1",{"id":5},[13,14,15],"p",{},"可读性是衡量代码是否书写优秀的一个重要指标，良好的可读性有助于阅读的开发者理解代码本身的意图，便于后续的修改和维护。在编写过程中或 Code Review 时，可以依照以下依据来判断代码是否具备良好的可读性：",[17,18,20],"h2",{"id":19},"naming","变量和方法的命名",[22,23,24],"blockquote",{},[13,25,26],{},"变量命名是一门学问 —— 沃兹基硕德",[28,29,31],"h3",{"id":30},"principle","原则",[13,33,34],{},"最重要的一点是，保持语法的正确性。避免书写如下的代码",[36,37,42],"pre",{"className":38,"code":39,"language":40,"meta":41,"style":41},"language-js shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F Bad\nfunction checkNowStatus() {}\nfunction goNextUrl() {}\n\n\u002F\u002F Good\nfunction checkCurrentStatus() {}\nfunction redirectToNextURL() {}\n","js","",[43,44,45,54,72,84,91,97,109],"code",{"__ignoreMap":41},[46,47,50],"span",{"class":48,"line":49},"line",1,[46,51,53],{"class":52},"sHwdD","\u002F\u002F Bad\n",[46,55,57,61,65,69],{"class":48,"line":56},2,[46,58,60],{"class":59},"spNyl","function",[46,62,64],{"class":63},"s2Zo4"," checkNowStatus",[46,66,68],{"class":67},"sMK4o","()",[46,70,71],{"class":67}," {}\n",[46,73,75,77,80,82],{"class":48,"line":74},3,[46,76,60],{"class":59},[46,78,79],{"class":63}," goNextUrl",[46,81,68],{"class":67},[46,83,71],{"class":67},[46,85,87],{"class":48,"line":86},4,[46,88,90],{"emptyLinePlaceholder":89},true,"\n",[46,92,94],{"class":48,"line":93},5,[46,95,96],{"class":52},"\u002F\u002F Good\n",[46,98,100,102,105,107],{"class":48,"line":99},6,[46,101,60],{"class":59},[46,103,104],{"class":63}," checkCurrentStatus",[46,106,68],{"class":67},[46,108,71],{"class":67},[46,110,112,114,117,119],{"class":48,"line":111},7,[46,113,60],{"class":59},[46,115,116],{"class":63}," redirectToNextURL",[46,118,68],{"class":67},[46,120,71],{"class":67},[13,122,123],{},"在命名变量\u002F方法时，应该保持足够的区分度。例如：",[36,125,127],{"className":38,"code":126,"language":40,"meta":41,"style":41},"\u002F\u002F Bad\nconst name1 = '';\nconst name2 = '';\n\n\u002F\u002F Good\nconst originalName = '';\nconst currentName = '';\n",[43,128,129,133,151,164,168,172,185],{"__ignoreMap":41},[46,130,131],{"class":48,"line":49},[46,132,53],{"class":52},[46,134,135,138,142,145,148],{"class":48,"line":56},[46,136,137],{"class":59},"const",[46,139,141],{"class":140},"sTEyZ"," name1 ",[46,143,144],{"class":67},"=",[46,146,147],{"class":67}," ''",[46,149,150],{"class":67},";\n",[46,152,153,155,158,160,162],{"class":48,"line":74},[46,154,137],{"class":59},[46,156,157],{"class":140}," name2 ",[46,159,144],{"class":67},[46,161,147],{"class":67},[46,163,150],{"class":67},[46,165,166],{"class":48,"line":86},[46,167,90],{"emptyLinePlaceholder":89},[46,169,170],{"class":48,"line":93},[46,171,96],{"class":52},[46,173,174,176,179,181,183],{"class":48,"line":99},[46,175,137],{"class":59},[46,177,178],{"class":140}," originalName ",[46,180,144],{"class":67},[46,182,147],{"class":67},[46,184,150],{"class":67},[46,186,187,189,192,194,196],{"class":48,"line":111},[46,188,137],{"class":59},[46,190,191],{"class":140}," currentName ",[46,193,144],{"class":67},[46,195,147],{"class":67},[46,197,150],{"class":67},[13,199,200],{},"此外，一个好的变量名应该能够准确表达意图，例如：",[36,202,204],{"className":38,"code":203,"language":40,"meta":41,"style":41},"\u002F\u002F Bad\nconst lStatus = false;\n\u002F\u002F Good\nconst isLoading = false;\n",[43,205,206,210,225,229],{"__ignoreMap":41},[46,207,208],{"class":48,"line":49},[46,209,53],{"class":52},[46,211,212,214,217,219,223],{"class":48,"line":56},[46,213,137],{"class":59},[46,215,216],{"class":140}," lStatus ",[46,218,144],{"class":67},[46,220,222],{"class":221},"sfNiH"," false",[46,224,150],{"class":67},[46,226,227],{"class":48,"line":74},[46,228,96],{"class":52},[46,230,231,233,236,238,240],{"class":48,"line":86},[46,232,137],{"class":59},[46,234,235],{"class":140}," isLoading ",[46,237,144],{"class":67},[46,239,222],{"class":221},[46,241,150],{"class":67},[13,243,244],{},"前者虽然保持了区分度，但并不能让人直接理解其含义。",[13,246,247,248],{},"另外，可以避免用太短\u002F太长的名字，避免例如：",[249,250,251],"a",{"href":251,"rel":252},"https:\u002F\u002Fgithub.com\u002Feclipse\u002Forg.aspectj\u002Fblob\u002Fmaster\u002Forg.aspectj.matcher\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Faspectj\u002Fweaver\u002Fpatterns\u002FHasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor.java",[253],"nofollow",[28,255,257],{"id":256},"convention","约定",[13,259,260],{},"通常来说，我们可以按照如下的约定命名：",[262,263,264,272],"ul",{},[265,266,267,268],"li",{},"使用相同的书写规则，例如遵循代码风格指南中的约定，",[269,270,271],"strong",{},"全部使用 camelCase 格式",[265,273,274],{},"用正确的方式处理缩略词可以避免误会，但多数情况也可以不理会。例如",[36,276,278],{"className":38,"code":277,"language":40,"meta":41,"style":41},"\u002F\u002F Not the best\nfunction getCurrentUrl() {}\nfunction isSaasUser() {}\nfunction checkTceStatus() {}\n\n\u002F\u002F Good\nfunction getCurrentURL() {}\nfunction isSaaSUser() {}\nfunction checkTCEStatus() {}\n",[43,279,280,285,296,307,318,322,326,337,349],{"__ignoreMap":41},[46,281,282],{"class":48,"line":49},[46,283,284],{"class":52},"\u002F\u002F Not the best\n",[46,286,287,289,292,294],{"class":48,"line":56},[46,288,60],{"class":59},[46,290,291],{"class":63}," getCurrentUrl",[46,293,68],{"class":67},[46,295,71],{"class":67},[46,297,298,300,303,305],{"class":48,"line":74},[46,299,60],{"class":59},[46,301,302],{"class":63}," isSaasUser",[46,304,68],{"class":67},[46,306,71],{"class":67},[46,308,309,311,314,316],{"class":48,"line":86},[46,310,60],{"class":59},[46,312,313],{"class":63}," checkTceStatus",[46,315,68],{"class":67},[46,317,71],{"class":67},[46,319,320],{"class":48,"line":93},[46,321,90],{"emptyLinePlaceholder":89},[46,323,324],{"class":48,"line":99},[46,325,96],{"class":52},[46,327,328,330,333,335],{"class":48,"line":111},[46,329,60],{"class":59},[46,331,332],{"class":63}," getCurrentURL",[46,334,68],{"class":67},[46,336,71],{"class":67},[46,338,340,342,345,347],{"class":48,"line":339},8,[46,341,60],{"class":59},[46,343,344],{"class":63}," isSaaSUser",[46,346,68],{"class":67},[46,348,71],{"class":67},[46,350,352,354,357,359],{"class":48,"line":351},9,[46,353,60],{"class":59},[46,355,356],{"class":63}," checkTCEStatus",[46,358,68],{"class":67},[46,360,71],{"class":67},[262,362,363],{},[265,364,365],{},"命名标量常量时全部子母大写，命名类和枚举类型时首字母大写，其他情况保持首字母小写。",[36,367,369],{"className":38,"code":368,"language":40,"meta":41,"style":41},"\u002F\u002F Bad\nconst cookieDelimiter = ';'\nconst myComponent = Vue.extend({})\nconst orderStatus = { started: 1 }\n\n\u002F\u002F Good\nconst COOKIE_DELIMITER = ';'\nconst MyComponent = Vue.extend({})\nconst OrderStatus = { started: 1 }\n",[43,370,371,375,394,421,447,451,455,470,491],{"__ignoreMap":41},[46,372,373],{"class":48,"line":49},[46,374,53],{"class":52},[46,376,377,379,382,384,387,391],{"class":48,"line":56},[46,378,137],{"class":59},[46,380,381],{"class":140}," cookieDelimiter ",[46,383,144],{"class":67},[46,385,386],{"class":67}," '",[46,388,390],{"class":389},"sfazB",";",[46,392,393],{"class":67},"'\n",[46,395,396,398,401,403,406,409,412,415,418],{"class":48,"line":74},[46,397,137],{"class":59},[46,399,400],{"class":140}," myComponent ",[46,402,144],{"class":67},[46,404,405],{"class":140}," Vue",[46,407,408],{"class":67},".",[46,410,411],{"class":63},"extend",[46,413,414],{"class":140},"(",[46,416,417],{"class":67},"{}",[46,419,420],{"class":140},")\n",[46,422,423,425,428,430,433,437,440,444],{"class":48,"line":86},[46,424,137],{"class":59},[46,426,427],{"class":140}," orderStatus ",[46,429,144],{"class":67},[46,431,432],{"class":67}," {",[46,434,436],{"class":435},"swJcz"," started",[46,438,439],{"class":67},":",[46,441,443],{"class":442},"sbssI"," 1",[46,445,446],{"class":67}," }\n",[46,448,449],{"class":48,"line":93},[46,450,90],{"emptyLinePlaceholder":89},[46,452,453],{"class":48,"line":99},[46,454,96],{"class":52},[46,456,457,459,462,464,466,468],{"class":48,"line":111},[46,458,137],{"class":59},[46,460,461],{"class":140}," COOKIE_DELIMITER ",[46,463,144],{"class":67},[46,465,386],{"class":67},[46,467,390],{"class":389},[46,469,393],{"class":67},[46,471,472,474,477,479,481,483,485,487,489],{"class":48,"line":339},[46,473,137],{"class":59},[46,475,476],{"class":140}," MyComponent ",[46,478,144],{"class":67},[46,480,405],{"class":140},[46,482,408],{"class":67},[46,484,411],{"class":63},[46,486,414],{"class":140},[46,488,417],{"class":67},[46,490,420],{"class":140},[46,492,493,495,498,500,502,504,506,508],{"class":48,"line":351},[46,494,137],{"class":59},[46,496,497],{"class":140}," OrderStatus ",[46,499,144],{"class":67},[46,501,432],{"class":67},[46,503,436],{"class":435},[46,505,439],{"class":67},[46,507,443],{"class":442},[46,509,446],{"class":67},[262,511,512],{},[265,513,514],{},"布尔类型的变量通常使用能够作为定语的类型，例如【过去分词】\u002F【形容词】；如果能够以 is 或 has 开头更佳。例如",[36,516,518],{"className":38,"code":517,"language":40,"meta":41,"style":41},"\u002F\u002F Bad\nconst verify = true;\nconst activeEl = true;\nconst noNeg = true;\n\n\u002F\u002F Good\nconst verified = true;\nconst active = true;\nconst isPositive = true;\nconst hasQualified = true;\n",[43,519,520,524,538,551,564,568,572,585,598,611],{"__ignoreMap":41},[46,521,522],{"class":48,"line":49},[46,523,53],{"class":52},[46,525,526,528,531,533,536],{"class":48,"line":56},[46,527,137],{"class":59},[46,529,530],{"class":140}," verify ",[46,532,144],{"class":67},[46,534,535],{"class":221}," true",[46,537,150],{"class":67},[46,539,540,542,545,547,549],{"class":48,"line":74},[46,541,137],{"class":59},[46,543,544],{"class":140}," activeEl ",[46,546,144],{"class":67},[46,548,535],{"class":221},[46,550,150],{"class":67},[46,552,553,555,558,560,562],{"class":48,"line":86},[46,554,137],{"class":59},[46,556,557],{"class":140}," noNeg ",[46,559,144],{"class":67},[46,561,535],{"class":221},[46,563,150],{"class":67},[46,565,566],{"class":48,"line":93},[46,567,90],{"emptyLinePlaceholder":89},[46,569,570],{"class":48,"line":99},[46,571,96],{"class":52},[46,573,574,576,579,581,583],{"class":48,"line":111},[46,575,137],{"class":59},[46,577,578],{"class":140}," verified ",[46,580,144],{"class":67},[46,582,535],{"class":221},[46,584,150],{"class":67},[46,586,587,589,592,594,596],{"class":48,"line":339},[46,588,137],{"class":59},[46,590,591],{"class":140}," active ",[46,593,144],{"class":67},[46,595,535],{"class":221},[46,597,150],{"class":67},[46,599,600,602,605,607,609],{"class":48,"line":351},[46,601,137],{"class":59},[46,603,604],{"class":140}," isPositive ",[46,606,144],{"class":67},[46,608,535],{"class":221},[46,610,150],{"class":67},[46,612,614,616,619,621,623],{"class":48,"line":613},10,[46,615,137],{"class":59},[46,617,618],{"class":140}," hasQualified ",[46,620,144],{"class":67},[46,622,535],{"class":221},[46,624,150],{"class":67},[262,626,627],{},[265,628,629],{},"在 ES2015+ 中使用 Promise 类型时，使用【现在分词】来表示其类型。例如",[36,631,633],{"className":38,"code":632,"language":40,"meta":41,"style":41},"\u002F\u002F Bad\nconst image = loadImageAsync();\nawait image;\n\n\u002F\u002F Good\nconst loadingImage = loadImageAsync();\nawait loadingImage;\n",[43,634,635,639,655,666,670,674,689],{"__ignoreMap":41},[46,636,637],{"class":48,"line":49},[46,638,53],{"class":52},[46,640,641,643,646,648,651,653],{"class":48,"line":56},[46,642,137],{"class":59},[46,644,645],{"class":140}," image ",[46,647,144],{"class":67},[46,649,650],{"class":63}," loadImageAsync",[46,652,68],{"class":140},[46,654,150],{"class":67},[46,656,657,661,664],{"class":48,"line":74},[46,658,660],{"class":659},"s7zQu","await",[46,662,663],{"class":140}," image",[46,665,150],{"class":67},[46,667,668],{"class":48,"line":86},[46,669,90],{"emptyLinePlaceholder":89},[46,671,672],{"class":48,"line":93},[46,673,96],{"class":52},[46,675,676,678,681,683,685,687],{"class":48,"line":99},[46,677,137],{"class":59},[46,679,680],{"class":140}," loadingImage ",[46,682,144],{"class":67},[46,684,650],{"class":63},[46,686,68],{"class":140},[46,688,150],{"class":67},[46,690,691,693,696],{"class":48,"line":111},[46,692,660],{"class":659},[46,694,695],{"class":140}," loadingImage",[46,697,150],{"class":67},[262,699,700],{},[265,701,702],{},"在命名方法时，尽可能使用谓语+宾语的格式，也就是保持方法名的第一个词是【动词】；某些情况下当行为容易理解时，也可以单独使用【介词+间接宾语】。例如：",[36,704,706],{"className":38,"code":705,"language":40,"meta":41,"style":41},"\u002F\u002F Bad\nfunction taskCategory2Platform() {}\nfunction forEachList() {}\nfunction Json() {}\n\n\u002F\u002F Good\nfunction getPlatformByTaskCategory() {}\nfunction normalizeList() {}\nfunction toJSON() {}\n",[43,707,708,712,723,734,745,749,753,764,775],{"__ignoreMap":41},[46,709,710],{"class":48,"line":49},[46,711,53],{"class":52},[46,713,714,716,719,721],{"class":48,"line":56},[46,715,60],{"class":59},[46,717,718],{"class":63}," taskCategory2Platform",[46,720,68],{"class":67},[46,722,71],{"class":67},[46,724,725,727,730,732],{"class":48,"line":74},[46,726,60],{"class":59},[46,728,729],{"class":63}," forEachList",[46,731,68],{"class":67},[46,733,71],{"class":67},[46,735,736,738,741,743],{"class":48,"line":86},[46,737,60],{"class":59},[46,739,740],{"class":63}," Json",[46,742,68],{"class":67},[46,744,71],{"class":67},[46,746,747],{"class":48,"line":93},[46,748,90],{"emptyLinePlaceholder":89},[46,750,751],{"class":48,"line":99},[46,752,96],{"class":52},[46,754,755,757,760,762],{"class":48,"line":111},[46,756,60],{"class":59},[46,758,759],{"class":63}," getPlatformByTaskCategory",[46,761,68],{"class":67},[46,763,71],{"class":67},[46,765,766,768,771,773],{"class":48,"line":339},[46,767,60],{"class":59},[46,769,770],{"class":63}," normalizeList",[46,772,68],{"class":67},[46,774,71],{"class":67},[46,776,777,779,782,784],{"class":48,"line":351},[46,778,60],{"class":59},[46,780,781],{"class":63}," toJSON",[46,783,68],{"class":67},[46,785,71],{"class":67},[17,787,789],{"id":788},"avoid-dynamic-types","尽量避免动态类型",[13,791,792],{},"古人云，动态类型一时爽，代码重构火葬场。尽管 JavaScript 是动态类型语言，但从工程化的角度而言，还是应当尽可能保持静态类型保持鲁棒性，并通过约定联合类型的方式保持灵活性。",[36,794,796],{"className":38,"code":795,"language":40,"meta":41,"style":41},"\u002F\u002F Bad\nlet formatter = 'get_value';\nif (data.is_number) {\n    formatter = function (value) { return Number(value) }\n}\nreturn typeof formatter === 'string' ? data[formatter](value) : formatter(value);\n\n\u002F\u002F Good\nlet formatter = data.get_value;\nif (data.is_number) {\n    formatter = function (value) { return Number(value) }\n}\nreturn formatter(value);\n",[43,797,798,802,822,838,877,881,917,921,925,942,954,983,988],{"__ignoreMap":41},[46,799,800],{"class":48,"line":49},[46,801,53],{"class":52},[46,803,804,807,810,812,814,817,820],{"class":48,"line":56},[46,805,806],{"class":59},"let",[46,808,809],{"class":140}," formatter ",[46,811,144],{"class":67},[46,813,386],{"class":67},[46,815,816],{"class":389},"get_value",[46,818,819],{"class":67},"'",[46,821,150],{"class":67},[46,823,824,827,830,832,835],{"class":48,"line":74},[46,825,826],{"class":659},"if",[46,828,829],{"class":140}," (data",[46,831,408],{"class":67},[46,833,834],{"class":140},"is_number) ",[46,836,837],{"class":67},"{\n",[46,839,840,843,846,849,852,856,859,861,864,867,869,871,874],{"class":48,"line":86},[46,841,842],{"class":63},"    formatter",[46,844,845],{"class":67}," =",[46,847,848],{"class":59}," function",[46,850,851],{"class":67}," (",[46,853,855],{"class":854},"sHdIc","value",[46,857,858],{"class":67},")",[46,860,432],{"class":67},[46,862,863],{"class":659}," return",[46,865,866],{"class":63}," Number",[46,868,414],{"class":435},[46,870,855],{"class":140},[46,872,873],{"class":435},") ",[46,875,876],{"class":67},"}\n",[46,878,879],{"class":48,"line":93},[46,880,876],{"class":67},[46,882,883,886,889,891,894,896,899,901,904,907,909,912,915],{"class":48,"line":99},[46,884,885],{"class":659},"return",[46,887,888],{"class":67}," typeof",[46,890,809],{"class":140},[46,892,893],{"class":67},"===",[46,895,386],{"class":67},[46,897,898],{"class":389},"string",[46,900,819],{"class":67},[46,902,903],{"class":67}," ?",[46,905,906],{"class":140}," data[formatter](value) ",[46,908,439],{"class":67},[46,910,911],{"class":63}," formatter",[46,913,914],{"class":140},"(value)",[46,916,150],{"class":67},[46,918,919],{"class":48,"line":111},[46,920,90],{"emptyLinePlaceholder":89},[46,922,923],{"class":48,"line":339},[46,924,96],{"class":52},[46,926,927,929,931,933,936,938,940],{"class":48,"line":351},[46,928,806],{"class":59},[46,930,809],{"class":140},[46,932,144],{"class":67},[46,934,935],{"class":140}," data",[46,937,408],{"class":67},[46,939,816],{"class":140},[46,941,150],{"class":67},[46,943,944,946,948,950,952],{"class":48,"line":613},[46,945,826],{"class":659},[46,947,829],{"class":140},[46,949,408],{"class":67},[46,951,834],{"class":140},[46,953,837],{"class":67},[46,955,957,959,961,963,965,967,969,971,973,975,977,979,981],{"class":48,"line":956},11,[46,958,842],{"class":63},[46,960,845],{"class":67},[46,962,848],{"class":59},[46,964,851],{"class":67},[46,966,855],{"class":854},[46,968,858],{"class":67},[46,970,432],{"class":67},[46,972,863],{"class":659},[46,974,866],{"class":63},[46,976,414],{"class":435},[46,978,855],{"class":140},[46,980,873],{"class":435},[46,982,876],{"class":67},[46,984,986],{"class":48,"line":985},12,[46,987,876],{"class":67},[46,989,991,993,995,997],{"class":48,"line":990},13,[46,992,885],{"class":659},[46,994,911],{"class":63},[46,996,914],{"class":140},[46,998,150],{"class":67},[13,1000,1001],{},"除了变量外，对于函数参数类型和返回值类型，也应当尽可能注意这一点（但某些出于便利性\u002F兼容性的场景可以理解）。",[17,1003,1005],{"id":1004},"semanticization","使用合适的方法表达语义",[13,1007,1008],{},"JavaScript 中一些方法本来就是为了提升语义存在的。在合适的场景下，更适合使用这些方法。例如",[36,1010,1012],{"className":38,"code":1011,"language":40,"meta":41,"style":41},"\u002F\u002F Bad\nif (arr.find(x => this.isValid(x))) {}\n\u002F\u002F Good\nif (arr.some(x => this.isValid(x))) {}\n\n\u002F\u002F Bad\nconst result = [];\narr.forEach(item => {\n  if (item.enabled) result.push(item.value)\n});\n\u002F\u002F Good\nconst result = arr\n  .filter(item => item.enabled)\n  .map(item => item.value)\n\n\u002F\u002F Bad\narr.map(item => {\n  item.value = this.getValue(item.key)\n})\n\u002F\u002F Good\narr.forEach(item => {\n  item.value = this.getValue(item.key)\n})\n\n\u002F\u002F Bad\nlet sum = 0;\narr.forEach(item => {\n  sum += item.value;\n})\n\u002F\u002F Good\nconst sum = arr.reduce((total, item) => total + item.value, 0)\n",[43,1013,1014,1018,1050,1054,1079,1083,1087,1101,1121,1155,1164,1168,1179,1201,1222,1227,1232,1249,1277,1284,1289,1306,1331,1338,1343,1348,1363,1380,1397,1404,1409],{"__ignoreMap":41},[46,1015,1016],{"class":48,"line":49},[46,1017,53],{"class":52},[46,1019,1020,1022,1025,1027,1030,1032,1035,1038,1041,1044,1047],{"class":48,"line":56},[46,1021,826],{"class":659},[46,1023,1024],{"class":140}," (arr",[46,1026,408],{"class":67},[46,1028,1029],{"class":63},"find",[46,1031,414],{"class":140},[46,1033,1034],{"class":854},"x",[46,1036,1037],{"class":59}," =>",[46,1039,1040],{"class":67}," this.",[46,1042,1043],{"class":63},"isValid",[46,1045,1046],{"class":140},"(x))) ",[46,1048,1049],{"class":67},"{}\n",[46,1051,1052],{"class":48,"line":74},[46,1053,96],{"class":52},[46,1055,1056,1058,1060,1062,1065,1067,1069,1071,1073,1075,1077],{"class":48,"line":86},[46,1057,826],{"class":659},[46,1059,1024],{"class":140},[46,1061,408],{"class":67},[46,1063,1064],{"class":63},"some",[46,1066,414],{"class":140},[46,1068,1034],{"class":854},[46,1070,1037],{"class":59},[46,1072,1040],{"class":67},[46,1074,1043],{"class":63},[46,1076,1046],{"class":140},[46,1078,1049],{"class":67},[46,1080,1081],{"class":48,"line":93},[46,1082,90],{"emptyLinePlaceholder":89},[46,1084,1085],{"class":48,"line":99},[46,1086,53],{"class":52},[46,1088,1089,1091,1094,1096,1099],{"class":48,"line":111},[46,1090,137],{"class":59},[46,1092,1093],{"class":140}," result ",[46,1095,144],{"class":67},[46,1097,1098],{"class":140}," []",[46,1100,150],{"class":67},[46,1102,1103,1106,1108,1111,1113,1116,1118],{"class":48,"line":339},[46,1104,1105],{"class":140},"arr",[46,1107,408],{"class":67},[46,1109,1110],{"class":63},"forEach",[46,1112,414],{"class":140},[46,1114,1115],{"class":854},"item",[46,1117,1037],{"class":59},[46,1119,1120],{"class":67}," {\n",[46,1122,1123,1126,1128,1130,1132,1135,1137,1140,1142,1145,1147,1149,1151,1153],{"class":48,"line":351},[46,1124,1125],{"class":659},"  if",[46,1127,851],{"class":435},[46,1129,1115],{"class":140},[46,1131,408],{"class":67},[46,1133,1134],{"class":140},"enabled",[46,1136,873],{"class":435},[46,1138,1139],{"class":140},"result",[46,1141,408],{"class":67},[46,1143,1144],{"class":63},"push",[46,1146,414],{"class":435},[46,1148,1115],{"class":140},[46,1150,408],{"class":67},[46,1152,855],{"class":140},[46,1154,420],{"class":435},[46,1156,1157,1160,1162],{"class":48,"line":613},[46,1158,1159],{"class":67},"}",[46,1161,858],{"class":140},[46,1163,150],{"class":67},[46,1165,1166],{"class":48,"line":956},[46,1167,96],{"class":52},[46,1169,1170,1172,1174,1176],{"class":48,"line":985},[46,1171,137],{"class":59},[46,1173,1093],{"class":140},[46,1175,144],{"class":67},[46,1177,1178],{"class":140}," arr\n",[46,1180,1181,1184,1187,1189,1191,1193,1196,1198],{"class":48,"line":990},[46,1182,1183],{"class":67},"  .",[46,1185,1186],{"class":63},"filter",[46,1188,414],{"class":140},[46,1190,1115],{"class":854},[46,1192,1037],{"class":59},[46,1194,1195],{"class":140}," item",[46,1197,408],{"class":67},[46,1199,1200],{"class":140},"enabled)\n",[46,1202,1204,1206,1209,1211,1213,1215,1217,1219],{"class":48,"line":1203},14,[46,1205,1183],{"class":67},[46,1207,1208],{"class":63},"map",[46,1210,414],{"class":140},[46,1212,1115],{"class":854},[46,1214,1037],{"class":59},[46,1216,1195],{"class":140},[46,1218,408],{"class":67},[46,1220,1221],{"class":140},"value)\n",[46,1223,1225],{"class":48,"line":1224},15,[46,1226,90],{"emptyLinePlaceholder":89},[46,1228,1230],{"class":48,"line":1229},16,[46,1231,53],{"class":52},[46,1233,1235,1237,1239,1241,1243,1245,1247],{"class":48,"line":1234},17,[46,1236,1105],{"class":140},[46,1238,408],{"class":67},[46,1240,1208],{"class":63},[46,1242,414],{"class":140},[46,1244,1115],{"class":854},[46,1246,1037],{"class":59},[46,1248,1120],{"class":67},[46,1250,1252,1255,1257,1259,1261,1263,1266,1268,1270,1272,1275],{"class":48,"line":1251},18,[46,1253,1254],{"class":140},"  item",[46,1256,408],{"class":67},[46,1258,855],{"class":140},[46,1260,845],{"class":67},[46,1262,1040],{"class":67},[46,1264,1265],{"class":63},"getValue",[46,1267,414],{"class":435},[46,1269,1115],{"class":140},[46,1271,408],{"class":67},[46,1273,1274],{"class":140},"key",[46,1276,420],{"class":435},[46,1278,1280,1282],{"class":48,"line":1279},19,[46,1281,1159],{"class":67},[46,1283,420],{"class":140},[46,1285,1287],{"class":48,"line":1286},20,[46,1288,96],{"class":52},[46,1290,1292,1294,1296,1298,1300,1302,1304],{"class":48,"line":1291},21,[46,1293,1105],{"class":140},[46,1295,408],{"class":67},[46,1297,1110],{"class":63},[46,1299,414],{"class":140},[46,1301,1115],{"class":854},[46,1303,1037],{"class":59},[46,1305,1120],{"class":67},[46,1307,1309,1311,1313,1315,1317,1319,1321,1323,1325,1327,1329],{"class":48,"line":1308},22,[46,1310,1254],{"class":140},[46,1312,408],{"class":67},[46,1314,855],{"class":140},[46,1316,845],{"class":67},[46,1318,1040],{"class":67},[46,1320,1265],{"class":63},[46,1322,414],{"class":435},[46,1324,1115],{"class":140},[46,1326,408],{"class":67},[46,1328,1274],{"class":140},[46,1330,420],{"class":435},[46,1332,1334,1336],{"class":48,"line":1333},23,[46,1335,1159],{"class":67},[46,1337,420],{"class":140},[46,1339,1341],{"class":48,"line":1340},24,[46,1342,90],{"emptyLinePlaceholder":89},[46,1344,1346],{"class":48,"line":1345},25,[46,1347,53],{"class":52},[46,1349,1351,1353,1356,1358,1361],{"class":48,"line":1350},26,[46,1352,806],{"class":59},[46,1354,1355],{"class":140}," sum ",[46,1357,144],{"class":67},[46,1359,1360],{"class":442}," 0",[46,1362,150],{"class":67},[46,1364,1366,1368,1370,1372,1374,1376,1378],{"class":48,"line":1365},27,[46,1367,1105],{"class":140},[46,1369,408],{"class":67},[46,1371,1110],{"class":63},[46,1373,414],{"class":140},[46,1375,1115],{"class":854},[46,1377,1037],{"class":59},[46,1379,1120],{"class":67},[46,1381,1383,1386,1389,1391,1393,1395],{"class":48,"line":1382},28,[46,1384,1385],{"class":140},"  sum",[46,1387,1388],{"class":67}," +=",[46,1390,1195],{"class":140},[46,1392,408],{"class":67},[46,1394,855],{"class":140},[46,1396,150],{"class":67},[46,1398,1400,1402],{"class":48,"line":1399},29,[46,1401,1159],{"class":67},[46,1403,420],{"class":140},[46,1405,1407],{"class":48,"line":1406},30,[46,1408,96],{"class":52},[46,1410,1412,1414,1416,1418,1421,1423,1426,1428,1430,1433,1436,1438,1440,1442,1445,1448,1450,1452,1454,1456,1458],{"class":48,"line":1411},31,[46,1413,137],{"class":59},[46,1415,1355],{"class":140},[46,1417,144],{"class":67},[46,1419,1420],{"class":140}," arr",[46,1422,408],{"class":67},[46,1424,1425],{"class":63},"reduce",[46,1427,414],{"class":140},[46,1429,414],{"class":67},[46,1431,1432],{"class":854},"total",[46,1434,1435],{"class":67},",",[46,1437,1195],{"class":854},[46,1439,858],{"class":67},[46,1441,1037],{"class":59},[46,1443,1444],{"class":140}," total ",[46,1446,1447],{"class":67},"+",[46,1449,1195],{"class":140},[46,1451,408],{"class":67},[46,1453,855],{"class":140},[46,1455,1435],{"class":67},[46,1457,1360],{"class":442},[46,1459,420],{"class":140},[13,1461,1462,1463,1467],{},"但注意不要滥用。例如我小时候曾经写过一篇 ",[249,1464,1465],{"href":1465,"rel":1466},"https:\u002F\u002Fgithub.com\u002FCyanSalt\u002Fnotebook\u002Fissues\u002F17",[253]," 主张使用 some 代替 forEach，但请勿在生产场景下这样使用。",[17,1469,1471],{"id":1470},"abstract","抽象、抽象，以及抽象",[13,1473,1474],{},"重要的事情说三遍，抽象的意思就是尽可能的把可复用的部分\u002F功能独立的部分单独剥离出来。通常来说你可以按照如下原则来对照：",[262,1476,1477,1480,1483,1486],{},[265,1478,1479],{},"相同的代码不写两遍，包括现在以及未来",[265,1481,1482],{},"在一个作用域下，对同一个路径的属性只访问一次；如果还有第二次，那么它应当被赋值给一个变量",[265,1484,1485],{},"如果在模板\u002FJSX中循环生成一个 VirtualDOM，并且它有自己的数据逻辑，那么它应当被单独抽象成一个组件",[265,1487,1488],{},"……",[13,1490,1491],{},"但同时也要注意，过渡的抽象也是不好的，可能会造成修改成本的提高。抽象的原则取决于你如何理解一段代码的功能，是仅仅服务于你的代码本身的，还是可能被其他部分复用的。如果是前者，尽量将它改的通用，或者是通过命名和注释标注。",[17,1493,1495],{"id":1494},"keep-pure","保持函数的纯度",[13,1497,1498],{},"纯函数是 FP 领域的常见称呼，在 React\u002FRedux 横行的当下也算是在 JS 届有一定地位。通常我们认为纯函数更加适合表达一段独立的逻辑，这主要是由其特点决定的。",[13,1500,1501,1502,1505],{},"纯函数的一个判定方式就是",[269,1503,1504],{},"幂等性","，也就是说，对于相同的参数，不论在什么场景下调用，都会产生相同的结果。考虑以下方法",[36,1507,1509],{"className":38,"code":1508,"language":40,"meta":41,"style":41},"function addItem(arr, item) {\n  arr.push(item)\n  return arr\n}\n",[43,1510,1511,1530,1545,1552],{"__ignoreMap":41},[46,1512,1513,1515,1518,1520,1522,1524,1526,1528],{"class":48,"line":49},[46,1514,60],{"class":59},[46,1516,1517],{"class":63}," addItem",[46,1519,414],{"class":67},[46,1521,1105],{"class":854},[46,1523,1435],{"class":67},[46,1525,1195],{"class":854},[46,1527,858],{"class":67},[46,1529,1120],{"class":67},[46,1531,1532,1535,1537,1539,1541,1543],{"class":48,"line":56},[46,1533,1534],{"class":140},"  arr",[46,1536,408],{"class":67},[46,1538,1144],{"class":63},[46,1540,414],{"class":435},[46,1542,1115],{"class":140},[46,1544,420],{"class":435},[46,1546,1547,1550],{"class":48,"line":74},[46,1548,1549],{"class":659},"  return",[46,1551,1178],{"class":140},[46,1553,1554],{"class":48,"line":86},[46,1555,876],{"class":67},[13,1557,1558],{},"显然不是一个纯函数，因为如果不停的对一个数组调用，这个数组将会越来越大。下面的写法就更“纯”一些：",[36,1560,1562],{"className":38,"code":1561,"language":40,"meta":41,"style":41},"function addItem(arr, item) {\n  return arr.concat([item])\n}\n",[43,1563,1564,1582,1601],{"__ignoreMap":41},[46,1565,1566,1568,1570,1572,1574,1576,1578,1580],{"class":48,"line":49},[46,1567,60],{"class":59},[46,1569,1517],{"class":63},[46,1571,414],{"class":67},[46,1573,1105],{"class":854},[46,1575,1435],{"class":67},[46,1577,1195],{"class":854},[46,1579,858],{"class":67},[46,1581,1120],{"class":67},[46,1583,1584,1586,1588,1590,1593,1596,1598],{"class":48,"line":56},[46,1585,1549],{"class":659},[46,1587,1420],{"class":140},[46,1589,408],{"class":67},[46,1591,1592],{"class":63},"concat",[46,1594,1595],{"class":435},"([",[46,1597,1115],{"class":140},[46,1599,1600],{"class":435},"])\n",[46,1602,1603],{"class":48,"line":74},[46,1604,876],{"class":67},[13,1606,1607,1608,1611],{},"不纯的函数最显著的问题是存在",[269,1609,1610],{},"副作用","，这在 JavaScript 中尤其严重，因为 JS 中是可以访问函数作用域上层的变量的。考虑下面的递归",[36,1613,1615],{"className":38,"code":1614,"language":40,"meta":41,"style":41},"function doSomething(node) {\n  const iterateNode = () => {\n    if (node && node.children) {\n      for (let child of node.children) {\n        node = child\n        node.setAttribute('data-track', String(Math.random()).slice(2))\n        iterateNode()\n      }\n    }\n  }\n}\n",[43,1616,1617,1633,1650,1674,1699,1709,1758,1766,1771,1776,1781],{"__ignoreMap":41},[46,1618,1619,1621,1624,1626,1629,1631],{"class":48,"line":49},[46,1620,60],{"class":59},[46,1622,1623],{"class":63}," doSomething",[46,1625,414],{"class":67},[46,1627,1628],{"class":854},"node",[46,1630,858],{"class":67},[46,1632,1120],{"class":67},[46,1634,1635,1638,1641,1643,1646,1648],{"class":48,"line":56},[46,1636,1637],{"class":59},"  const",[46,1639,1640],{"class":140}," iterateNode",[46,1642,845],{"class":67},[46,1644,1645],{"class":67}," ()",[46,1647,1037],{"class":59},[46,1649,1120],{"class":67},[46,1651,1652,1655,1657,1659,1662,1665,1667,1670,1672],{"class":48,"line":74},[46,1653,1654],{"class":659},"    if",[46,1656,851],{"class":435},[46,1658,1628],{"class":140},[46,1660,1661],{"class":67}," &&",[46,1663,1664],{"class":140}," node",[46,1666,408],{"class":67},[46,1668,1669],{"class":140},"children",[46,1671,873],{"class":435},[46,1673,837],{"class":67},[46,1675,1676,1679,1681,1683,1686,1689,1691,1693,1695,1697],{"class":48,"line":86},[46,1677,1678],{"class":659},"      for",[46,1680,851],{"class":435},[46,1682,806],{"class":59},[46,1684,1685],{"class":140}," child",[46,1687,1688],{"class":67}," of",[46,1690,1664],{"class":140},[46,1692,408],{"class":67},[46,1694,1669],{"class":140},[46,1696,873],{"class":435},[46,1698,837],{"class":67},[46,1700,1701,1704,1706],{"class":48,"line":93},[46,1702,1703],{"class":140},"        node",[46,1705,845],{"class":67},[46,1707,1708],{"class":140}," child\n",[46,1710,1711,1713,1715,1718,1720,1722,1725,1727,1729,1732,1734,1737,1739,1742,1745,1747,1750,1752,1755],{"class":48,"line":99},[46,1712,1703],{"class":140},[46,1714,408],{"class":67},[46,1716,1717],{"class":63},"setAttribute",[46,1719,414],{"class":435},[46,1721,819],{"class":67},[46,1723,1724],{"class":389},"data-track",[46,1726,819],{"class":67},[46,1728,1435],{"class":67},[46,1730,1731],{"class":63}," String",[46,1733,414],{"class":435},[46,1735,1736],{"class":140},"Math",[46,1738,408],{"class":67},[46,1740,1741],{"class":63},"random",[46,1743,1744],{"class":435},"())",[46,1746,408],{"class":67},[46,1748,1749],{"class":63},"slice",[46,1751,414],{"class":435},[46,1753,1754],{"class":442},"2",[46,1756,1757],{"class":435},"))\n",[46,1759,1760,1763],{"class":48,"line":111},[46,1761,1762],{"class":63},"        iterateNode",[46,1764,1765],{"class":435},"()\n",[46,1767,1768],{"class":48,"line":339},[46,1769,1770],{"class":67},"      }\n",[46,1772,1773],{"class":48,"line":351},[46,1774,1775],{"class":67},"    }\n",[46,1777,1778],{"class":48,"line":613},[46,1779,1780],{"class":67},"  }\n",[46,1782,1783],{"class":48,"line":956},[46,1784,876],{"class":67},[13,1786,1787],{},"可能直觉看上去挺合理的，但是实际上它只会遍历到每个元素的第一个子元素，因为 node = child 这个操作实际上是一个副作用，它修改的是函数的外部变量。上述代码的纯函数写法应该是",[36,1789,1791],{"className":38,"code":1790,"language":40,"meta":41,"style":41},"function doSomething(node) {\n  const iterateNode = (element) => {\n    if (element && element.children) {\n      for (let child of element.children) {\n        child.setAttribute('data-track', String(Math.random()).slice(2))\n        iterateNode(child)\n      }\n    }\n  }\n  iterateNode(node)\n}\n",[43,1792,1793,1807,1826,1847,1869,1910,1921,1925,1929,1933,1944],{"__ignoreMap":41},[46,1794,1795,1797,1799,1801,1803,1805],{"class":48,"line":49},[46,1796,60],{"class":59},[46,1798,1623],{"class":63},[46,1800,414],{"class":67},[46,1802,1628],{"class":854},[46,1804,858],{"class":67},[46,1806,1120],{"class":67},[46,1808,1809,1811,1813,1815,1817,1820,1822,1824],{"class":48,"line":56},[46,1810,1637],{"class":59},[46,1812,1640],{"class":140},[46,1814,845],{"class":67},[46,1816,851],{"class":67},[46,1818,1819],{"class":854},"element",[46,1821,858],{"class":67},[46,1823,1037],{"class":59},[46,1825,1120],{"class":67},[46,1827,1828,1830,1832,1834,1836,1839,1841,1843,1845],{"class":48,"line":74},[46,1829,1654],{"class":659},[46,1831,851],{"class":435},[46,1833,1819],{"class":140},[46,1835,1661],{"class":67},[46,1837,1838],{"class":140}," element",[46,1840,408],{"class":67},[46,1842,1669],{"class":140},[46,1844,873],{"class":435},[46,1846,837],{"class":67},[46,1848,1849,1851,1853,1855,1857,1859,1861,1863,1865,1867],{"class":48,"line":86},[46,1850,1678],{"class":659},[46,1852,851],{"class":435},[46,1854,806],{"class":59},[46,1856,1685],{"class":140},[46,1858,1688],{"class":67},[46,1860,1838],{"class":140},[46,1862,408],{"class":67},[46,1864,1669],{"class":140},[46,1866,873],{"class":435},[46,1868,837],{"class":67},[46,1870,1871,1874,1876,1878,1880,1882,1884,1886,1888,1890,1892,1894,1896,1898,1900,1902,1904,1906,1908],{"class":48,"line":93},[46,1872,1873],{"class":140},"        child",[46,1875,408],{"class":67},[46,1877,1717],{"class":63},[46,1879,414],{"class":435},[46,1881,819],{"class":67},[46,1883,1724],{"class":389},[46,1885,819],{"class":67},[46,1887,1435],{"class":67},[46,1889,1731],{"class":63},[46,1891,414],{"class":435},[46,1893,1736],{"class":140},[46,1895,408],{"class":67},[46,1897,1741],{"class":63},[46,1899,1744],{"class":435},[46,1901,408],{"class":67},[46,1903,1749],{"class":63},[46,1905,414],{"class":435},[46,1907,1754],{"class":442},[46,1909,1757],{"class":435},[46,1911,1912,1914,1916,1919],{"class":48,"line":99},[46,1913,1762],{"class":63},[46,1915,414],{"class":435},[46,1917,1918],{"class":140},"child",[46,1920,420],{"class":435},[46,1922,1923],{"class":48,"line":111},[46,1924,1770],{"class":67},[46,1926,1927],{"class":48,"line":339},[46,1928,1775],{"class":67},[46,1930,1931],{"class":48,"line":351},[46,1932,1780],{"class":67},[46,1934,1935,1938,1940,1942],{"class":48,"line":613},[46,1936,1937],{"class":63},"  iterateNode",[46,1939,414],{"class":435},[46,1941,1628],{"class":140},[46,1943,420],{"class":435},[46,1945,1946],{"class":48,"line":956},[46,1947,876],{"class":67},[13,1949,1950],{},"这样就可以正常的工作。",[13,1952,1953],{},"通常来说问题并不会像上面的例子这样简单，但使用纯函数很多时候可以避免一些潜在的 bug。对于 coder 而言，一个很重要的能力就是意识到自己的代码哪些地方产生了副作用，以及这些副作用是否符合预期，或者是否在合适的时机被消除。",[17,1955,1957],{"id":1956},"keep-trust","保持信任，不避讳异常",[13,1959,1960],{},"很多时候我们喜欢写这样的代码：",[36,1962,1964],{"className":38,"code":1963,"language":40,"meta":41,"style":41},"{\n  template: '\u003Cdiv>{{ name }}\u003C\u002Fdiv>',\n  props: {\n    info: {\n      type: Object,\n    },\n  },\n  computed: {\n    name() {\n      return this.info.author && this.info.author.name\n    },\n  }\n}\n",[43,1965,1966,1970,1988,1997,2006,2018,2023,2028,2037,2047,2077,2081,2085],{"__ignoreMap":41},[46,1967,1968],{"class":48,"line":49},[46,1969,837],{"class":67},[46,1971,1972,1976,1978,1980,1983,1985],{"class":48,"line":56},[46,1973,1975],{"class":1974},"sBMFI","  template",[46,1977,439],{"class":67},[46,1979,386],{"class":67},[46,1981,1982],{"class":389},"\u003Cdiv>{{ name }}\u003C\u002Fdiv>",[46,1984,819],{"class":67},[46,1986,1987],{"class":67},",\n",[46,1989,1990,1993,1995],{"class":48,"line":74},[46,1991,1992],{"class":1974},"  props",[46,1994,439],{"class":67},[46,1996,1120],{"class":67},[46,1998,1999,2002,2004],{"class":48,"line":86},[46,2000,2001],{"class":1974},"    info",[46,2003,439],{"class":67},[46,2005,1120],{"class":67},[46,2007,2008,2011,2013,2016],{"class":48,"line":93},[46,2009,2010],{"class":1974},"      type",[46,2012,439],{"class":67},[46,2014,2015],{"class":140}," Object",[46,2017,1987],{"class":67},[46,2019,2020],{"class":48,"line":99},[46,2021,2022],{"class":67},"    },\n",[46,2024,2025],{"class":48,"line":111},[46,2026,2027],{"class":67},"  },\n",[46,2029,2030,2033,2035],{"class":48,"line":339},[46,2031,2032],{"class":1974},"  computed",[46,2034,439],{"class":67},[46,2036,1120],{"class":67},[46,2038,2039,2042,2045],{"class":48,"line":351},[46,2040,2041],{"class":63},"    name",[46,2043,2044],{"class":435},"() ",[46,2046,837],{"class":67},[46,2048,2049,2052,2054,2057,2059,2062,2064,2066,2068,2070,2072,2074],{"class":48,"line":613},[46,2050,2051],{"class":659},"      return",[46,2053,1040],{"class":67},[46,2055,2056],{"class":140},"info",[46,2058,408],{"class":67},[46,2060,2061],{"class":140},"author",[46,2063,1661],{"class":67},[46,2065,1040],{"class":67},[46,2067,2056],{"class":140},[46,2069,408],{"class":67},[46,2071,2061],{"class":140},[46,2073,408],{"class":67},[46,2075,2076],{"class":140},"name\n",[46,2078,2079],{"class":48,"line":956},[46,2080,2022],{"class":67},[46,2082,2083],{"class":48,"line":985},[46,2084,1780],{"class":67},[46,2086,2087],{"class":48,"line":990},[46,2088,876],{"class":67},[13,2090,2091,2092,2095,2096,2099],{},"这通常来说很有效，尤其是在 ES2020 中你甚至可以直接 ",[43,2093,2094],{},"info?.author.name","，更加方便了。但是，这样更多时候只是让你看不到 ",[43,2097,2098],{},"\"Cannot read property 'name' of undefined\""," 而已，很容易因为这样的写法忽略了一些问题，例如：",[262,2101,2102,2105,2108],{},[265,2103,2104],{},"是否 author 本应是必传的，而外部忘记了传递？",[265,2106,2107],{},"是否 author 不存在意味着加载尚未完成，此时应该展示 loading 而不是空白的 div 元素？",[265,2109,2110],{},"是否当 author 不存在时，外部就不应该渲染 MyComponent 元素？",[13,2112,2113],{},"通常来说，这样的“防御”更像是蒙住眼睛不去管这些问题。通常来说，尽管有相同的结果，但更鼓励大家这样实现：",[36,2115,2117],{"className":38,"code":2116,"language":40,"meta":41,"style":41},"{\n  template: '\u003Cdiv>{{ name }}\u003C\u002Fdiv>',\n  props: {\n    info: {\n      type: Object,\n      required: true,\n      \u002F\u002F 一种可能的情况是通过 validator 直接校验 props，但注意 props 校验仅在开发环境生效\n      \u002F\u002F validator(value) {\n      \u002F\u002F   return Boolean(value.author)\n      \u002F\u002F },\n    },\n  },\n  computed: {\n    name() {\n      \u002F\u002F 显式地表达“这里 author 有可能为空，这种情况就单独处理”，而不是忽略这个问题\n      if (!this.info.author) return ''\n      return this.info.author.name\n    },\n  }\n}\n",[43,2118,2119,2123,2137,2145,2153,2163,2174,2179,2184,2189,2194,2198,2202,2210,2218,2223,2246,2262,2266,2270],{"__ignoreMap":41},[46,2120,2121],{"class":48,"line":49},[46,2122,837],{"class":67},[46,2124,2125,2127,2129,2131,2133,2135],{"class":48,"line":56},[46,2126,1975],{"class":1974},[46,2128,439],{"class":67},[46,2130,386],{"class":67},[46,2132,1982],{"class":389},[46,2134,819],{"class":67},[46,2136,1987],{"class":67},[46,2138,2139,2141,2143],{"class":48,"line":74},[46,2140,1992],{"class":1974},[46,2142,439],{"class":67},[46,2144,1120],{"class":67},[46,2146,2147,2149,2151],{"class":48,"line":86},[46,2148,2001],{"class":1974},[46,2150,439],{"class":67},[46,2152,1120],{"class":67},[46,2154,2155,2157,2159,2161],{"class":48,"line":93},[46,2156,2010],{"class":1974},[46,2158,439],{"class":67},[46,2160,2015],{"class":140},[46,2162,1987],{"class":67},[46,2164,2165,2168,2170,2172],{"class":48,"line":99},[46,2166,2167],{"class":1974},"      required",[46,2169,439],{"class":67},[46,2171,535],{"class":221},[46,2173,1987],{"class":67},[46,2175,2176],{"class":48,"line":111},[46,2177,2178],{"class":52},"      \u002F\u002F 一种可能的情况是通过 validator 直接校验 props，但注意 props 校验仅在开发环境生效\n",[46,2180,2181],{"class":48,"line":339},[46,2182,2183],{"class":52},"      \u002F\u002F validator(value) {\n",[46,2185,2186],{"class":48,"line":351},[46,2187,2188],{"class":52},"      \u002F\u002F   return Boolean(value.author)\n",[46,2190,2191],{"class":48,"line":613},[46,2192,2193],{"class":52},"      \u002F\u002F },\n",[46,2195,2196],{"class":48,"line":956},[46,2197,2022],{"class":67},[46,2199,2200],{"class":48,"line":985},[46,2201,2027],{"class":67},[46,2203,2204,2206,2208],{"class":48,"line":990},[46,2205,2032],{"class":1974},[46,2207,439],{"class":67},[46,2209,1120],{"class":67},[46,2211,2212,2214,2216],{"class":48,"line":1203},[46,2213,2041],{"class":63},[46,2215,2044],{"class":435},[46,2217,837],{"class":67},[46,2219,2220],{"class":48,"line":1224},[46,2221,2222],{"class":52},"      \u002F\u002F 显式地表达“这里 author 有可能为空，这种情况就单独处理”，而不是忽略这个问题\n",[46,2224,2225,2228,2230,2233,2235,2237,2239,2241,2243],{"class":48,"line":1229},[46,2226,2227],{"class":659},"      if",[46,2229,851],{"class":435},[46,2231,2232],{"class":67},"!this.",[46,2234,2056],{"class":140},[46,2236,408],{"class":67},[46,2238,2061],{"class":140},[46,2240,873],{"class":435},[46,2242,885],{"class":659},[46,2244,2245],{"class":67}," ''\n",[46,2247,2248,2250,2252,2254,2256,2258,2260],{"class":48,"line":1234},[46,2249,2051],{"class":659},[46,2251,1040],{"class":67},[46,2253,2056],{"class":140},[46,2255,408],{"class":67},[46,2257,2061],{"class":140},[46,2259,408],{"class":67},[46,2261,2076],{"class":140},[46,2263,2264],{"class":48,"line":1251},[46,2265,2022],{"class":67},[46,2267,2268],{"class":48,"line":1279},[46,2269,1780],{"class":67},[46,2271,2272],{"class":48,"line":1286},[46,2273,876],{"class":67},[13,2275,2276],{},"这种问题同样发生在函数参数上，有时候，不给函数参数提供默认值，也是一种提前发现错误的方式；此外，对于异步过程的调用（Promise\u002Fasync function）也有类似的情况。",[17,2278,2280],{"id":2279},"end","尾声",[36,2282,2286],{"className":2283,"code":2284,"language":2285,"meta":41,"style":41},"language-sh shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","node -e \"console.log(require('child_process').execSync('python -c \\'import this\\'').toString())\"\n","sh",[43,2287,2288],{"__ignoreMap":41},[46,2289,2290],{"class":48,"line":49},[46,2291,2284],{},[22,2293,2294,2297],{},[13,2295,2296],{},"Python 之道 - Tim Peters",[13,2298,2299,2300,2303,2304,2306,2307,2309,2310,2312,2313,2315,2316,2318,2319,2321,2322,2324,2325,2327,2328,2330,2331,2334,2335,2337,2338,2340],{},"优美胜于丑陋。",[2301,2302],"br",{},"\n显式胜于隐式。",[2301,2305],{},"\n简洁胜于复杂。",[2301,2308],{},"\n复杂胜于凌乱。",[2301,2311],{},"\n扁平胜于嵌套。",[2301,2314],{},"\n稀疏胜于紧凑。",[2301,2317],{},"\n可读性很重要。",[2301,2320],{},"\n实用性大于保持纯净，但特例不足以打破这些规则。",[2301,2323],{},"\n错误不应静默地消逝，除非明确地沉默。",[2301,2326],{},"\n面对模棱两可时切勿猜测，总会有一个——最好是唯一的——显然的方式，尽管在一开始可能并不明显，除非你是大佬。",[2301,2329],{},"\n现状胜于未来，尽管未来通常胜于",[269,2332,2333],{},"当下","的现状。",[2301,2336],{},"\n难以解释的实现都是坏主意，易于解释的实现可能会是好主意。",[2301,2339],{},"\n命名空间就是一个超棒的主意——来做更多这样的事情！",[2342,2343,2344],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}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 .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}",{"title":41,"searchDepth":56,"depth":56,"links":2346},[2347,2351,2352,2353,2354,2355,2356],{"id":19,"depth":56,"text":20,"children":2348},[2349,2350],{"id":30,"depth":74,"text":31},{"id":256,"depth":74,"text":257},{"id":788,"depth":56,"text":789},{"id":1004,"depth":56,"text":1005},{"id":1470,"depth":56,"text":1471},{"id":1494,"depth":56,"text":1495},{"id":1956,"depth":56,"text":1957},{"id":2279,"depth":56,"text":2280},"2020-05-28","md",{},"\u002Fposts\u002Fmake-your-code-more-readable",{"title":5,"description":15},"posts\u002F2020\u002Fmake-your-code-more-readable","mvWwXI48LkbZ_QPHM8iLaA9T-9bjLm0_rlFBNXbp1p8",[2365,2366],null,{"title":2367,"path":2368,"stem":2369,"children":-1},"JS Why Not 系列","\u002Fposts\u002Fjs-why-not","posts\u002F2020\u002Fjs-why-not",1792500630765]