编写高质量代码,孙悟空的三个锦囊

来源:http://www.hdxcsm.com 作者:政治头条 人气:191 发布时间:2019-08-09
摘要:《编写高质量代码:改善JavaScript程序的188个建议》 本信息 作者: 成林 出版社:机械工业出版社 ISBN:9787111399056 上架时间:2012-11-6 出版日期:2013 年1月 开本:16开 页码:1 版次:1-1 所

ca88 1

《编写高质量代码:改善JavaScript程序的188个建议》
本信息
作者: 成林
出版社:机械工业出版社
ISBN:9787111399056
上架时间:2012-11-6
出版日期:2013 年1月
开本:16开
页码:1
版次:1-1
所属分类: 计算机 > 软件与程序设计 > 网络编程 > javascript
ca88 2

根据《编写高质量代码改善JavaScript程序的188个建议》这本书,来记录我目前所了解的建议方式。

 第一部分 语言篇

第1章 基本语言要素 / 2
建议1:正确操作字符串 / 2
建议2:使用默认转型方法 / 6
建议3:区别对待强制转型与as和is / 9
建议4:TryParse比Parse好 / 12
建议5:使用int?来确保值类型也可以为null / 15
建议6:区别readonly和const的使用方法 / 16
建议7:将0值作为枚举的默认值 / 19
建议8:避免给枚举类型的元素提供显式的值 / 20
建议9:习惯重载运算符 / 22
建议10:创建对象时需要考虑是否实现比较器 / 23
建议11:区别对待==和Equals / 27
建议12:重写Equals时也要重写GetHashCode / 29
建议13:为类型输出格式化字符串 / 32
建议14:正确实现浅拷贝和深拷贝 / 36
建议15:使用dynamic来简化反射实现 / 40

第2章 集合和LINQ / 43
建议16:元素数量可变的情况下不应使用数组 / 43
建议17:多数情况下使用foreach进行循环遍历 / 45
建议18:foreach不能代替for / 51
建议19:使用更有效的对象和集合初始化 / 53
建议20:使用泛型集合代替非泛型集合 / 54
建议21:选择正确的集合 / 57
建议22:确保集合的线程安全 / 61
建议23:避免将List作为自定义集合类的基类 / 64
建议24:迭代器应该是只读的 / 67
建议25:谨慎集合属性的可写操作 / 68
建议26:使用匿名类型存储LINQ查询结果 / 70
建议27:在查询中使用Lambda表达式 / 73
建议28:理解延迟求值和主动求值之间的区别 / 75
建议29:区别LINQ查询中的IEnumerable和IQueryable / 78
建议30:使用LINQ取代集合中的比较器和迭代器 / 80
建议31:在LINQ查询中避免不必要的迭代 / 83

第3章 泛型、委托和事件 / 86
建议32:总是优先考虑泛型 / 86
建议33:避免在泛型类型中声明静态成员 / 88
建议34:为泛型参数设定约束 / 90
建议35:使用default为泛型类型变量指定初始值 / 92
建议36:使用FCL中的委托声明 / 94
建议37:使用Lambda表达式代替方法和匿名方法 / 96
建议38:小心闭包中的陷阱 / 99
建议39:了解委托的实质 / 103
建议40:使用event关键字为委托施加保护 / 106
建议41:实现标准的事件模型 / 108
建议42:使用泛型参数兼容泛型接口的不可变性 / 109
建议43:让接口中的泛型参数支持协变 / 111
建议44:理解委托中的协变 / 112
建议45:为泛型类型参数指定逆变 / 114

第4章 资源管理和序列化 / 116
建议46:显式释放资源需继承接口IDisposable / 116
建议47:即使提供了显式释放方法,也应该在终结器中提供隐式清理 / 119
建议48:Dispose方法应允许被多次调用 / 120
建议49:在Dispose模式中应提取一个受保护的虚方法 / 121
建议50:在Dispose模式中应区别对待托管资源和非托管资源 / 123
建议51:具有可释放字段的类型或拥有本机资源的类型应该是可释放的 / 124
建议52:及时释放资源 / 125
建议53:必要时应将不再使用的对象引用赋值为null / 127
建议54:为无用字段标注不可序列化 / 131
建议55:利用定制特性减少可序列化的字段 / 136
建议56:使用继承ISerializable接口更灵活地控制序列化过程 / 137
建议57:实现ISerializable的子类型应负责父类的序列化 / 140

第5章 异常与自定义异常 / 144
建议58:用抛出异常代替返回错误代码 / 144
建议59:不要在不恰当的场合下引发异常 / 147
建议60:重新引发异常时使用Inner Exception / 150
建议61:避免在finally内撰写无效代码 / 151
建议62:避免嵌套异常 / 157
建议63:避免“吃掉”异常 / 160
建议64:为循环增加Tester-Doer模式而不是将try-catch置于循环内 / 161
建议65:总是处理未捕获的异常 / 162
建议66:正确捕获多线程中的异常 / 166
建议67:慎用自定义异常 / 168
建议68:从System.Exception或其他常见的基本异常中派生异常 / 170
建议69:应使用finally避免资源泄漏 / 172
建议70:避免在调用栈较低的位置记录异常 / 175

第6章 异步、多线程、任务和并行 / 177
建议71:区分异步和多线程应用场景 / 177
建议72:在线程同步中使用信号量 / 180
建议73:避免锁定不恰当的同步对象 / 184
建议74:警惕线程的IsBackground / 188
建议75:警惕线程不会立即启动 / 189
建议76:警惕线程的优先级 / 191
建议77:正确停止线程 / 193
建议78:应避免线程数量过多 / 194
建议79:使用ThreadPool或BackgroundWorker代替Thread / 196
建议80:用Task代替ThreadPool / 198
建议81:使用Parallel简化同步状态下Task的使用 / 202
建议82:Parallel简化但不等同于Task默认行为 / 204
建议83:小心Parallel中的陷阱 / 205
建议84:使用PLINQ / 208
建议85:Task中的异常处理 / 209
建议86:Parallel中的异常处理 / 214
建议87:区分WPF和WinForm的线程模型 / 216
建议88:并行并不总是速度更快 / 220
建议89:在并行方法体中谨慎使用锁 / 222

“有困难,找代表”。每年全国两会,人大代表提出的建议都备受关注。这些建议都有啥?落实情况怎么样?人民日报特别推出微动画——“孙悟空的三个锦囊”,为你解读。

更多关于 》》》《编写高质量代码:改善JavaScript程序的188个建议》
内容简介
书籍
计算机书籍
  《编写高质量代码:改善javascript程序的188个建议》是web前端工程师进阶修炼的必读之作,将为你通往“javascript技术殿堂”指点迷津!内容全部由编写高质量的javascript代码的最佳实践组成,从基本语法、应用架构、工具框架、编码风格、编程思想等5大方面对web前端工程师遇到的疑难问题给出了经验性的解决方案,为web前端工程师如何编写更高质量的javascript代码提供了188条极为宝贵的建议。对于每一个问题,不仅以建议的方式给出了被实践证明为十分优秀的解决方案,而且还给出了经常被误用或被错误理解的不好的解决方案,从正反两个方面进行了分析和对比,犹如醍醐灌顶,让人豁然开朗。
  《编写高质量代码:改善javascript程序的188个建议》针对每个问题所设计的应用场景都非常典型,给出的建议也都与实践紧密结合。书中的每一条建议都可能在你的下一行代码、下一个应用或下一个项目中被用到,建议你将此书放置在手边,随时查阅,一定能使你的学习和开发工作事半功倍。
目录
《编写高质量代码:改善javascript程序的188个建议》
前  言
第1章 javascript语言基础 / 1
建议1:警惕unicode乱码 / 1
建议2:正确辨析javascript句法中的词、句和段 / 2
建议3:减少全局变量污染 / 4
建议4:注意javascript数据类型的特殊性 / 6
建议5:防止javascript自动插入分号 / 11
建议6:正确处理javascript特殊值 / 12
建议7:小心保留字的误用 / 15
建议8:谨慎使用运算符 / 16
建议9:不要信任hasownproperty / 20
建议10:谨记对象非空特性 / 20
建议11:慎重使用伪数组 / 21
建议12:避免使用with / 22
建议13:养成优化表达式的思维方式 / 23
建议14:不要滥用eval / 26
建议15:避免使用continue / 27
建议16:防止switch贯穿 / 28
建议17:块标志并非多余 / 29
建议18:比较function语句和function表达式 / 29
建议19:不要使用类型构造器 / 30
建议20:不要使用new / 31
建议21:推荐提高循环性能的策略 / 31
建议22:少用函数迭代 / 35
建议23:推荐提高条件性能的策略 / 35
建议24:优化if逻辑 / 36
建议25:恰当选用if和switch / 39
建议26:小心if嵌套的思维陷阱 / 40
建议27:小心if隐藏的bug / 42
建议28:使用查表法提高条件检测的性能 / 43
建议29:准确使用循环体 / 44
建议30:使用递归模式 / 48
建议31:使用迭代 / 49
建议32:使用制表 / 50
建议33:优化循环结构 / 51
第2章 字符串、正则表达式和数组 / 53
建议34:字符串是非值操作 / 53
建议35:获取字节长度 / 55
建议36:警惕字符串连接操作 / 56
建议37:推荐使用replace / 59
建议38:正确认识正则表达式工作机制 / 62
建议39:正确理解正则表达式回溯 / 63
建议40:正确使用正则表达式分组 / 65
建议41:正确使用正则表达式引用 / 68
建议42:用好正则表达式静态值 / 69
建议43:使用exec增强正则表达式功能 / 71
建议44:正确使用原子组 / 72
建议45:警惕嵌套量词和回溯失控 / 73
建议46:提高正则表达式执行效率 / 74
建议47:避免使用正则表达式的场景 / 76
建议48:慎用正则表达式修剪字符串 / 77
建议49:比较数组与对象同源特性 / 80
建议50:正确检测数组类型 / 81
建议51:理解数组长度的有限性和无限性 / 82
建议52:建议使用splice删除数组 / 83
建议53:小心使用数组维度 / 84
建议54:增强数组排序的sort功能 / 85
建议55:不要拘泥于数字下标 / 87
建议56:使用arguments模拟重载 / 89
第3章 函数式编程 / 91
建议57:禁用function构造函数 / 91
建立58:灵活使用arguments / 94
建议59:推荐动态调用函数 / 96
建议60:比较函数调用模式 / 99
建议61:使用闭包跨域开发 / 101
建议62:在循环体和异步回调中慎重使用闭包 / 104
建议63:比较函数调用和引用本质 / 106
建议64:建议通过function扩展类型 / 108
建议65:比较函数的惰性求值与非惰性求值 / 109
建议66:使用函数实现历史记录 / 111
建议67:套用函数 / 113
建议68:推荐使用链式语法 / 114
建议69:使用模块化规避缺陷 / 115
建议70:惰性实例化 / 117
建议71:推荐分支函数 / 118
建议72:惰性载入函数 / 119
ca88,建议73:函数绑定有价值 / 121
建议74:使用高阶函数 / 123
建议75:函数柯里化 / 125
建议76:要重视函数节流 / 126
建议77:推荐作用域安全的构造函数 / 127
建议78:正确理解执行上下文和作用域链 / 129
第4章 面向对象编程 / 133
建议79:参照object构造体系分析prototype机制 / 133
建议80:合理使用原型 / 137
建议81:原型域链不是作用域链 / 140
建议82:不要直接检索对象属性值 / 142
建议83:使用原型委托 / 143
建议84:防止原型反射 / 144
建议85:谨慎处理对象的scope / 145
建议86:使用面向对象模拟继承 / 149
建议87:分辨this和function调用关系 / 152
建议88:this是动态指针,不是静态引用 / 153
建议89:正确应用this / 157
建议90:预防this误用的策略 / 161
建议91:推荐使用构造函数原型模式定义类 / 164
建议92:不建议使用原型继承 / 166
建议93:推荐使用类继承 / 168
建议94:建议使用封装类继承 / 171
建议95:慎重使用实例继承 / 172
建议96:避免使用复制继承 / 174
建议97:推荐使用混合继承 / 175
建议98:比较使用javascript多态、重载和覆盖 / 176
建议99:建议主动封装类 / 179
建议100:谨慎使用类的静态成员 / 181
建议101:比较类的构造和析构特性 / 183
建议102:使用享元类 / 186
建议103:使用掺元类 / 188
建议104:谨慎使用伪类 / 190
建议105:比较单例的两种模式 / 192
第5章 dom编程 / 195
建议106:建议先检测浏览器对dom支持程度 / 195
建议107:应理清html dom加载流程 / 198
建议108:谨慎访问dom / 200
建议109:比较innerhtml与标准dom方法 / 200
建议110:警惕文档遍历中的空格bug / 202
建议111:克隆节点比创建节点更好 / 203
建议112:谨慎使用html集合 / 204
建议113:用局部变量访问集合元素 / 206
建议114:使用nextsibling抓取dom / 207
建议115:实现dom原型继承机制 / 207
建议116:推荐使用css选择器 / 210
建议117:减少dom重绘和重排版次数 / 211
建议118:使用dom树结构托管事件 / 216
建议119:使用定时器优化ui 队列 / 217
建议120:使用定时器分解任务 / 220
建议121:使用定时器限时运行代码 / 221
建议122:推荐网页工人线程 / 222
第6章 客户端编程 / 226
建议123:比较ie和w3c事件流 / 226
建议124:设计鼠标拖放方案 / 229
建议125:设计鼠标指针定位方案 / 231
建议126:小心在元素内定位鼠标指针 / 233
建议127:妥善使用domcontentloaded事件 / 234
建议128:推荐使用beforeunload事件 / 236
建议129:自定义事件 / 236
建议130:从css样式表中抽取元素尺寸 / 238
建议131:慎重使用offsetwidth和offsetheight / 241
建议132:正确计算区域大小 / 244
建议133:谨慎计算滚动区域大小 / 247
建议134:避免计算窗口大小 / 248
建议135:正确获取绝对位置 / 249
建议136:正确获取相对位置 / 251
第7章 数据交互和存储 / 254
建议137:使用隐藏框架实现异步通信 / 254
建议138:使用iframe实现异步通信 / 257
建议139:使用script实现异步通信 / 259
建议140:正确理解jsonp异步通信协议 / 264
建议141:比较常用的服务器请求方法 / 267
建议142:比较常用的服务器发送数据方法 / 271
建议143:避免使用xml格式进行通信 / 273
建议144:推荐使用json格式进行通信 / 275
建议145:慎重使用html格式进行通信 / 278
建议146:使用自定义格式进行通信 / 279
建议147:ajax性能向导 / 280
建议148:使用本地存储数据 / 281
建议149:警惕基于dom的跨域侵入 / 283
建议150:优化ajax开发的最佳实践 / 286
建议151:数据存储要考虑访问速度 / 290
建议152:使用局部变量存储数据 / 291
建议153:警惕人为改变作用域链 / 293
建议154:慎重使用动态作用域 / 294
建议155:小心闭包导致内存泄漏 / 295
建议156:灵活使用cookie存储长信息 / 296
建议157:推荐封装cookie应用接口 / 298
第8章 javascript引擎与兼容性 / 300
建议158:比较主流浏览器内核解析 / 300
建议159:推荐根据浏览器特性进行检测 / 302
建议160:关注各种引擎对ecmascript v3的分歧 / 305
建议161:关注各种引擎对ecmascript v3的补充 / 316
建议162:关注各种引擎对event解析的分歧 / 327
建议163:关注各种引擎对dom解析的分歧 / 330
建议164:关注各种引擎对css渲染的分歧 / 335
第9章 javascript编程规范和应用 / 339
建议165:不要混淆javascript与浏览器 / 339
建议166:掌握javascript预编译过程 / 340
建议167:准确分析javascript执行顺序 / 344
建议168:避免二次评估 / 350
建议169:建议使用直接量 / 351
建议170:不要让javascript引擎重复工作 / 351
建议171:使用位操作符执行逻辑运算 / 353
建议172:推荐使用原生方法 / 355
建议173:编写无阻塞javascript脚本 / 356
建议174:使脚本延迟执行 / 358
建议175:使用xhr脚本注入 / 362
建议176:推荐最优化非阻塞模式 / 362
建议177:避免深陷作用域访问 / 363
建议178:推荐的javascript性能调优 / 365
建议179:减少dom操作中的repaint和reflow / 368
建议180:提高dom访问效率 / 370
建议181:使用 settimeout实现工作线程 / 372
建议182:使用 web worker / 375
建议183:避免内存泄漏 / 377
建议184:使用svg创建动态图形 / 380
建议185:减少对象成员访问 / 385
建议186:推荐100 ms用户体验 / 388
建议187:使用接口解决javascript文件冲突 / 390
建议188:避免javascript与css冲突 / 392

建议1:警惕Unicode乱码

第二部分 架构篇

第7章 成员设计 / 226
建议90:不要为抽象类提供公开的构造方法 / 226
建议91:可见字段应该重构为属性 / 226
建议92:谨慎将数组或集合作为属性 / 227
建议93:构造方法应初始化主要属性和字段 / 228
建议94:区别对待override和new / 229
建议95:避免在构造方法中调用虚成员 / 235
建议96:成员应优先考虑公开基类型或接口 / 236
建议97:优先考虑将基类型或接口作为参数传递 / 237
建议98:用params减少重复参数 / 237
建议99:重写时不应使用子类参数 / 238
建议100:静态方法和实例方法没有区别 / 239
建议101:使用扩展方法,向现有类型“添加”方法 / 240

第8章 类型设计 / 243
建议102:区分接口和抽象类的应用场合 / 243
建议103:区分组合和继承的应用场合 / 245
建议104:用多态代替条件语句 / 248
建议105:使用私有构造函数强化单例 / 251
建议106:为静态类添加静态构造函数 / 253
建议107:区分静态类和单例 / 255
建议108:将类型标识为sealed / 255
建议109:谨慎使用嵌套类 / 256
建议110:用类来代替enum / 257
建议111:避免双向耦合 / 260
建议112:将现实世界中的对象抽象为类,将可复用对象圈起来就是命名空间 / 262

第9章 安全性设计 / 264
建议113:声明变量前考虑最大值 / 264
建议114:MD5不再安全 / 265
建议115:通过HASH来验证文件是否被篡改 / 268
建议116:避免用非对称算法加密文件 / 269
建议117:使用SSL确保通信中的数据安全 / 273
建议118:使用SecureString保存密钥等机密字符串 / 284
建议119:不要使用自己的加密算法 / 289
建议120:为程序集指定强名称 / 289
建议121:为应用程序设定运行权限 / 291

本图书信息来源:中国互动出版网

ca88 3ca88 4

第三部分 编码规范及习惯

第10章 命名规范 / 296
建议122:以.为命名空间命名 / 296
建议123:程序集不必与命名空间同名 / 296
建议124:考虑在命名空间中使用复数 / 297
建议125:避免用FCL的类型名称命名自己的类型 / / 297
建议126:用名词和名词组给类型命名 / 298
建议127:用形容词组给接口命名 / 299
建议128:考虑让派生类的名字以基类名字作为后缀 / 300
建议129:泛型类型参数要以T作为前缀 / 300
建议130:以复数命名枚举类型,以单数命名枚举元素 / 301
建议131:用PascalCasing命名公开元素 / 302
建议132:考虑用类名作为属性名 / 302
建议133:用camelCasing命名私有字段和局部变量 / 303
建议134:有条件地使用前缀 / 304
建议135: 考虑使用肯定性的短语命名布尔属性 / 305
建议136:优先使用后缀表示已有类型的新版本 / 306
建议137:委托和事件类型应添加上级后缀 / 307
建议138:事件和委托变量使用动词或形容词短语命名 / 308
建议139:事件处理器命名采用组合方式 / 309

第11章 代码整洁 / 311
建议140:使用默认的访问修饰符 / 311
建议141:不知道该不该用大括号时,就用 / 312
建议142:总是提供有意义的命名 / 314
建议143:方法抽象级别应在同一层次 / 315
建议144:一个方法只做一件事 / 316
建议145:避免过长的方法和过长的类 / 317
建议146:只对外公布必要的操作 / 318
建议147:重构多个相关属性为一个类 / 319
建议148:不重复代码 / 320
建议149:使用表驱动法避免过长的if和switch分支 / 321
建议150:使用匿名方法、Lambda表达式代替方法 / 324
建议151:使用事件访问器替换公开的事件成员变量 / 325
建议152:最少,甚至是不要注释 / 326
建议153:若抛出异常,则必须要注释 / 326

第12章 规范开发行为 / 327
建议154:不要过度设计,在敏捷中体会重构的乐趣 / 327
建议155:随生产代码一起提交单元测试代码 / 336
建议156:利用特性为应用程序提供多个版本 / 342
建议157:从写第一个界面开始,就进行自动化测试 / 344

 

根据ECMA标准规定JavaScript语言可以使用中文来命名变量或函数名,例如:

var 人名 = “张三”;
function 睡觉(谁){
  alert(谁   ":快睡觉!都半夜三更了。");
}

睡觉(人名);

但是在ECMA标准化之前,JavaScript通常是不支持Unicode编码的,为了防止乱码,我们应该尽量使用基本字符进行编码。

建议1

建议2:正确辨析JavaScript句法中的词、句和段

ca88 5ca88 6

{
 //对象
}

function(){
 //函数
}

if(){
 //条件
}

for(){
 //循环
}

while(){
 //循环
}

switch(){
 //多条件
}

with(){
 //作用于
}

try(){
  //异常处理
}

建议2

建议3:减少全局变量污染

ca88 7ca88 8

在任何函数外面直接执行var语句
var f = “value”;

直接添加一个属性到全局对象上,全局对象是所有全局变量的容器,在Web浏览器中,全局对象名为window
window.f = “value”;

直接使用未经声明的变量,以这种方式定义的全局变量被称为隐式的全局变量
f = “value”;

建议3

建议4:注意JavaScript数据类型的特殊性

ca88 9

ca88 10

ca88 11

ca88 12ca88 13

1.防止浮点数溢出

num = 0.1 0.2; //0.3000000000000000004

针对上面相加可以这么进行处理:

a = (1 2)/10; //0.3

2.慎用JavaScript类型自动转换







 3.正确检测数据类型



4.避免误用parseInt

parseInt("123abc");  //123     parseInt("1.73"); //1        parseInt(".123"); //NAA

var d = "010";  //八进制   var e ="0x10";   //十六进制     parseInt(d); //8  parseInt(e); //16

建议4

建议5:防止JavaScript自动插入分号

ca88 14ca88 15

JavaScript会在解析时,自动在后面插入一个分号,但是在某些情况下是不允许插入分号的,否则会导致代码出错,例如:

var f = function(){return{status : true};

JavaScript 应该正确安全的实行 分行 显示,例如

var i = a ? 1 : b ? 2 : c ? 3 : 4;  //定义一个变量i,然后为其赋值,如果变量a为true则赋值为1,否则就判断变量b,如果b为true则赋值为2,否则就判断变量c,如果c为true则赋值为3,否则就赋值为4

应该写成

var i = a ? 1
          :b ? 2
          :c ? 3
          :4 ;

建议5

建议6:正确处理JavaScript特殊值

建议7:小心保留字的误用

ca88 16

ca88 17ca88 18

Javascr不建议使用任何保留字。如果一定要使用保留字,必须要用引号括起来,例如

object = {'case' : value};

object['case'] = value;

建议7

建议8:谨慎使用运算符

ca88 19ca88 20

 1. 用 ===,而不用 ==

' ' == 0 //false
0 == ' ' //true
0 == '0' //true
false == 'false' //false
false == '0' //true
falser == undefined //false
false == null //false
null == undefined //true

2.谨慎使用    和 --

var n = 4;
n  ;   
  n;

3.小心逗号运算符

var a = (1,2,3,4);
alert(a); //4

a=1,2,3,4;
alert(a);  //1

建议8

建议9:不要信任 hasOwnProperty

20

建议10:谨记对象非空特性

21

建议11:慎重使用伪数组

21

建议12:避免使用with

22

建议13:养成优化表达式的思维方式

ca88 21ca88 22

对于一个表达式稍加改动就会打乱表达式的逻辑运算顺序,因此我们应该学会优化表达式的结构。

1.第一种方式--加小括号

(a   b > c && a - b < c || a > b > c);

优化:

((a   b > c) && ((a - b < c) || (a > b > c)));

2.第二种方式--改变表达式结构顺序

例如,想要设计一个表达式来筛选学龄人群,既年龄大于或等于6岁且小于18岁的人,或者年龄大于或等于65岁的人

if(age >= 6 && age < 18 || age >= 65){}

优化:

if(6 <= age && age < 18 || 65 <= age){}

建议13

**建议14:不要滥用eval**

ca88 23ca88 24

eval是一个被滥用的很严重的JavaScript特征,通常情况下,eval函数传递一个字符串给JavaScript编译器,该字符串会被当成一段JavaScript程序来解析和执行,例如

eval(alert('提示'));

使用eval形式的代码会更难阅读,而且会使代码性能显著降低。

建议14

建议15:避免使用continue

ca88 25ca88 26

continue语句与break语句用法相似,在循环结构中用于控制逻辑的执行方向。break语句用于停止循环,而continue语句则用于再次执行循环,与break语句语法相同。

书上讲到,通过重构移动continue语句会使性能得到改善,在非必要条件下,建议不要使用continue语句。

但是,那break呢,是不是也可以不使用,从而使代码性能得到改善。

建议15

**建议16:防止switch贯穿**

ca88 27ca88 28

说白了,在写switch  case  break  default的时候,在写case之后,因为并没有指明终点,所以一定要写break,不然会使代码发生连续贯穿现象。

建议16

建议17:块标签并非多余

ca88 29ca88 30

在写if逻辑判断的时候,即使得到的条件只有一条,也应写上块标签,例如

if(0){
  if(1){
    alert(1);
  }
}
else{
  alert(0);
}

严格遵循规范,并始终使用代码块,会使代码更容易理解。

建议17

**建议18:比较function语句和function表达式**

建议19:不要使用类型构造器

 空

**建议20:不要使用new**

**建议21:推荐提高循环性能的策略**

**建议22:少用函数迭代**

ca88 31ca88 32

本地数组对象新增加了一个forEach方法,此方法遍历一个数组的所有成员。

JavaScript:

items.forEach(function(value,index,array){
  process(value);
});
JQuery:

$.each(items,function(index,value){
  process(value);
});

尽管基于函数的迭代使用起来非常便利,但是比基于循环的迭代更慢一些,每个数组项要关联额外的函数调用是造成速度慢的主要原因。因此,在非特殊需求下,不建议使用函数迭代。

建议22

**建议23:推荐提高条件性能的策略**

ca88 33ca88 34

//条件少

if(found){
}else{
}

//条件多

switch(color){
  case "red":
           break;
  case "blue":
           break;

  case "brown":
           break;

  default:
}

在大多数情况下,switch比if运行更快,但是只有当条件体数量很大时才明显,它们之间主要性能区别在于,当条件体增加时,if性能负担增加的程度比switch更大,因此,在性能上讲,如果条件体少,应使用if,如果条件体多,应使用switch。

建议23

**建议24:优化if逻辑**

ca88 35ca88 36

if(value < 5){
}else if(value >5 && value <10){
}else{
}

可以看得出,如果条件体value大多在小于5的情况下,是最优的,但是在大于5且小于10之间,需要通过一次条件判断,如果大于10,就需要判断3次,所以,得根据情况写if逻辑

建议24

**建议25:恰当选用if和switch**

ca88 37ca88 38

表达式的值是连续的线性判断,显然用if结构会更合适一些,例如:如果分数小于60,不及格,分数在60~75(不包括75),合格,分数在75~85(不包括85),良好,分数在85~100,优秀

if(score < 60){
  alert("不及格");
}else if (60 <= score < 75){
  alert("及格");
}else if (75 <= score < 85){
  alert("良好");
}else if(85 <= socre <= 100){
  alert("优秀");
}

对于有限制的枚举数据,比如性别,使用switch结构会更高效,例如:

switch(sex){
  case "女“:
    alert("女士");
  break;
  case "男“:
    alert("男士");
  break;
  default:
    alert("请选择性别");
}

建议25

**建议26:小心if嵌套的思维陷阱**

ca88 39ca88 40

人的思维是很复杂的,一般遇到一些逻辑判断的时候,人们会

if(a){
  if(b){
      if(c){
        if(d){
          alert("所有条件都成立!");
        }
        else{
          alert("条件d不成立!");
        }
     }
     else{
       alert("条件c不成立!");
     }
   }
   else{
     alert("条件b不成立!");
   }
}
else{
  alert("条件a不成立");
}

一般可以采用排除法来优化上面例子

var t = true; //初始化为true
if(!a){
  alert("条件a不成立!");

  t=false;
}

if(!b){
  alert("条件b不成立!");

  t=false;
}

if(!c){
  alert("条件c不成立!");

  t=false;
}

if(!d){
  alert("条件d不成立!");

  t=false;
}

if(t){
  alert("所有条件都成立!");

}

排除法虽然有效地避免了条件结构的多重嵌套,并且更加符合人的思维模式,但是,也是有一定的局限性,在条件判断时,如果有一个发生错误,那就会终止,放弃后面的操作,如果仅仅是为了检查某个值的合理性,也就无所谓了,但是如果为了改变变量值和数据操作,那么直接放弃就会让后面的数据操作也无法进行,为了防止此类问题,可以再设计一个标志变量来跟踪整个操作行为。

建议26

**建议27:小心if隐藏的Bug**

ca88 41ca88 42

很多程序员会犯过这样的低级错误:
if(a = 1){
  alert(a);
}
虽然它是一个合法的表达式,不会导致编译错误,但是由于此表达的返回值为非0数值,JavaScript会自动把它转化为true,因此这样的分支结构的条件永远成立。
为了防止出现这样低级而令人讨厌的错误,我们建议:
if(1 == a){
  alert(a);
}

建议27

**建议28:使用查表法提高条件检测的性能**

ca88 43ca88 44

当有大量离散值需要测试时,使用if和switch比使用查表法要慢得多,在JavaScript中查表法可通过数组或普通对象实现。
查表法访问数据,在条件体的数目很大时,查表法不仅非常快,而且当需要测试的离散值数量非常大时,也有办法保持代码的可读性。
例如,使用switch检测value值。
switch(value){
  case 0:
    return result0;
  case 1:
    return result1;
  case 2:
    return result2;
  case 3:
    return result3;
  case 4:
    return result4;
}
使用switch结构检测value值的代码所占的空间可能与switch的重要性不成比例,代码很笨重,整个结构可以用一个数组查询代替。
var result = [result0,result1,result2,result3,result4]
return results[value];

建议28

**建议29:准确使用循环体**

ca88 45ca88 46

选择正确的循环体会有助于提高性能及用户体验,一般来讲,有四种循环方式。例如:
1.for(var i=0;i<10;i  ){//循环体}
2.var i=0; while(i<10){//循环体 i  ;} //条件循环
3.var i=0;do{//循环体}while(i   < 10); //至少循环一次
4.for(var prop in object){//循环体}

其他循环体会比for in 循环快7倍,因此推荐这样做,除非需要对数目不详的对象属性进行操作,否则避免使用for in循环,例如,迭代遍历一个有限的、已知的属性列表,舒勇其他循环类型更快,具体的使用模式如下:
var prop = ["prop1","prop2"],i=0;
while(i<prop.length){ process(object[prop[i]]);}

if循环是有章可循的,我们可以很容易地预知循环的次数,每次循环的状态等信息。
while循环根据特定条件来决定循环操作,由于这个条件是动态的,无法预知条件何时为ture和flase。

因此,for结构尝尝呗用于有规律的重复操作,如数组、对象、集合。
对于对象的迭代操作,更适合用for in这种特殊的for循环来操作。
如果对条件有特殊要求的话,建议用while。
如果至少要执行一次的话,建议用do while。

建议29

**建议30:使用递归模式**

ca88 47ca88 48

那么什么叫递归呢?所谓递归函数就是在函数体内调用本函数。
最简单的例子就是计算阶乘。0和1的阶乘都会被定义为1,更大的数的阶乘是通过计算1*1*...来求得的,每次增加1,直至达到要计算阶乘的那个数。
function factorial(n){
  if(n<=1){
    return 1;  
  } 
  else{
    return n*factorial(n-1);
  }
}

建议30

建议31:使用迭代

ca88 49ca88 50

合并排序算法是最常用的以递归实现的算法。
function merge(left,right){
  var result=[];
  while(left.length>0&&right.length>0){
    if(left[0]<right[0]){
      result.push(left.shift()); 
    }else{
      result.push(right.shift());
    }
  }
   return result.concat(left).concat(right);
}


function mergeSort(items){
  if(items.length == 1){
    return items;
  }
  var middle = Math.floor(items.length/2), 
        left      = items.slice(0,middle),
        right    = items.slice(middle);
  return merge(mergeSort(left),mergeSort(right));
}

这个合并排序代码相当简单直接,其中mergeSort()函数被调用得非常频繁,对一个超过1500项的数组进行操作,就可能在Firefox上导致栈溢出,这就说明递归不是最好的实现方法,合并排序算法还可以用迭代实现,例如:
function mergeSort(items){
  if(items.length == 1){
    return items;
  }
  var work = [];
  for(var i = 0 , len = items.length; i<len; i  ){
    work.push([items[i]]);
  }
  work.push([]);
  for(var lim = len; lim > 1; lim=(lim 1) / 2){
    for(var j = 0,k = 0; k<lim; j  ,k =2){
      work[j] = merge(work[k],work[k 1]);
    }
    work[j] = [];
  }
  return work[0];
}

建议31

建议32:使用制表

建议33:优化循环结构

ca88 51ca88 52

循环是最浪费资源的一种流程。循环结构中一点小小的损耗都会被成倍放大,从而影响程序运行的效率。
1.优化结构
var a = true;
for(var b = 1; b < 10; b  ){ //循环结构
  if(a == true){
    //条件判断
  }
}
很明显,在这个循环结构中if语句会被反复执行,如果这个if语句是一个固定的条件检测表达式,也就是说,如果if语句的条件不会受循环结构的影响,那么不妨采用如下的结构来设计:
if(a == true){ //条件判断
  for(var b=1;b<10;b  ){
    //循环结构
  }
}
但是,如果这个if条件表达式受循环结构的制约,就不能够采用这种结构嵌套了。

建议33

本文由ca88发布于政治头条,转载请注明出处:编写高质量代码,孙悟空的三个锦囊

关键词: ca88

最火资讯