航天员|如何编写高质量 JavaScript 代码( 二 )



第四点:减少嵌套层级多层级的嵌套 , 如:条件嵌套、循环嵌套、回调嵌套等 , 对于代码阅读是非常不利的 , 所以应尽量减少嵌套的层级 。
像解决条件嵌套的问题 , 一般可采用卫语句(guard clause)的方式提前返回 , 从而减少嵌套 。
// badfunction foo() {  let result  if (isDead) {    result = deadAmount()   else {    if (isRet) {      result = retAmount()     else {      result = normalAmount()        return result// goodfunction foo() {  if (isDead) {    return deadAmount()    if (isRet) {    return retAmount()    return normalAmount()

除了卫语句外 , 通过还可以采用短路运算、条件运算符等进行条件语句的改写 。
// badlet fs = require(\"fs\")function init() {  fs.mkdir(root (err) => {    fs.mkdir(path.join(root \"public\" \"stylesheets\") (err) => {      fs.writeFile(        path.join(root \"public\" \"stylesheets\" \"style.css\")        \"\"        function (err) {      )    )  )init()// goodlet fs = require(\"fs\").promisesasync function init() {  await fs.mkdir(root)  await fs.mkdir(path.join(root \"public\" \"stylesheets\"))  await fs.writeFile(path.join(root \"public\" \"stylesheets\" \"style.css\") \"\")init

除了以上介绍的四点建议外 , 还有很多可以改善阅读体验的点 , 如:有效的注释、避免不同类型的比较、避免生涩的语法等等 。
高性能的代码在软件开发中 , 代码的性能高低会直接影响到产品的用户体验 , 所以高质量的代码必然是高性能的 。 这里总结了四点具体操作方式分享给大家 。
提示:测试JavaScript平均耗时 , 可使用console.time()方法、JSBench.Me工具、performance工具等 。
第一点:优化算法
递归是一种常见的算法 , 下面是用递归实现的“求阶乘”的操作 。
// badfunction foo(n) {  if (n === 1) {    return 1    return n * foo(n - 1)foo(100)   // 平均耗时:0.47ms// goodfunction foo(n result = 1) {  if (n === 1) {    return result    return foo(n - 1 n * result)    // 这里尾调用优化foo(100)   // 平均耗时:0.09ms

“尾调用”是一种可以重用栈帧的内存管理优化机制 , 即外部函数的返回值是一个内部函数的返回值 。
第二点:使用内置方法
很多功能都可以采用JavaScript内置方法来解决 , 往往内置方法的底层实现是最优的 , 并且内置方法可在解释器中提前执行 , 所以执行效率非常高 。
下面举例为:获取对象属性和值得复合数组形式 。
// badlet data = https://mparticle.uc.cn/api/{ username: /"leo\"  age: 20  gender: \"male\"let result = [
for (let attr in data) {  result.push([attr data[attr

)console.log(result)// goodlet data = https://mparticle.uc.cn/api/{ username: /"leo\"  age: 20  gender: \"male\"let result = Object.entries(data)console.log(result)

第三点:减少作用域链查找
作用域链是作用域规则的实现 , 通过作用域链的实现 , 变量在它的作用域内可被访问 , 函数在它的作用域内可被调用 。 作用域链是一个只能单向访问的链表 , 这个链表上的每个节点就是执行上下文的变量对象(代码执行时就是活动对象) , 单向链表的头部(可被第一个访问的节点)始终都是当前正在被调用执行的函数的变量对象(活动对象) , 尾部始终是全局活动对象 。
概念太复杂的话 ,看下面这样一张图 。


作者:子晨

作用域链这个链表就是 3(头部:bar) -> 2(foo) -> 1(尾部:全局) , 所以查找变量的时候 , 应尽量在头部完成获取 , 这样就可以节省性能 , 具体对比如下 。