编码指南

https://static.surmon.me/nodepress/image/ecmascript-2016.jpg

就三点:

  • 编码风格:忌简忌繁、统一风格
  • 编码结构:模块化、函数式、易读性、复用元素的抽象
  • 编码过程:扩展能力、测试

编码风格

保持良好的编码风格

  • 不要刻意简写难以理解的表达式,也不要嵌套过于冗余的函数
  • 缩进统一、命名统一、标符统一、文件结构统一...,一切能以标准量化的的都需要拿标准约束
  • Lint等QA约束工具是必须的,用工具来实践程序正义

更详细的编码规范,可以来这:Developer code guide

编码结构

Spaghetti code (面条代码)的特征

  • 代码没有组织,且多处出现重复的代码块

    • 一般是封装粒度不够造成
  • 多个代码块之间高度耦合,跳来跳去,使其难以调试

    • 函数抽象程度不够
    • OOP理解不深刻
    • 典型的命令式编程
  • 代码不会分解成条件块或标签,使其难以阅读。

    • 到这个程度就不知道代码写的有多糟了

避免面条代码的方法

  • 需要复用的代码一定要封装
  • “模块化”不仅仅是文件意义的模块化,而是指逻辑单元的模块化,比如函数;当然现在大部分框架、库、平台...都有自己成熟的模块化系统,在模块化的基础上尽量取得平衡
  • 函数的模块化和封装要尽量地“函数式”,不依赖外部变量,不改变外部变量,有输入,有输出,不过度嵌套,中间量清晰易读
  • 避免全局变量和类成员传递数据,函数内部更应该优先使用局部变量和参数变量
  • 优秀的代码是不需要注释的,所以命名本身很重要很重要

优秀的代码组织应该是清晰的树状结构,自上而下分解任务, 自下而上完成任务。

编码过程

防止 over-engineering (过度设计)

过度设计是指,太过于考虑今后代码的扩展性、复用性,或太过于考虑测试的便利性,导致系统被过度设计为难以理解、难以重用的复杂结构。

世界上有两种“没有bug”的代码。一种是“没有明显的bug的代码”,另一种是“明显没有bug的代码”。

第一种情况,由于代码复杂不堪,加上很多测试,各种coverage,看起来测试都通过了,所以就认为代码是正确的。

第二种情况,由于代码简单直接,就算没写很多测试,你一眼看去就知道它不可能有bug。

你钟爱哪一种?

防止过度设计的方法:

  • 先把眼前的问题解决掉,解决好,再考虑将来的扩展问题
  • 先写出可用的代码,反复推敲,再考虑是否需要重用的问题
  • 先写出可用,简单,明显没有bug的代码,再考虑测试的问题

代码规范可以参考上面链接就可以了,可以根据自己的情况修改规范以建立自己的标准,下面分享一些平日较为不易理解的代码片段。

隐式转换

==!=操作符会在需要的情况下自动转换数据类型; ===!==不会,它们会同时比较值和数据类型,也称为严格比较。

              
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
[10] === 10 // false [10] == 10 // true '10' == 10 // true '10' === 10 // false [] == 0 // true [] === 0 // false '' == false // true (but true == "a" is false,因为true隐式转换为字符串为'1') '' === false // false

赋值判断

              
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
// 正常流程 var a if (b) { a = b } else { a = c } // 三目运算 var a = b ? b : c // 利用短路运算判断赋值 var a = b || c

数据类型判断typeofinstanceof

              
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
/* typeof 会返回一个变量的基本类型,针对数组和对象均返回'object' */ typeof 666 // 'number' typeof Date() // 'string' typeof [] // 'object' typeof {} // 'object' typeof false // 'boolean' typeof new Function() // 'function' typeof undefined // 'undefined' typeof null // 'object' /* instanceof 仅检测对象的原型链是否指向构造函数的prototype对象 由于Javascript中万物皆对象,故一切用new关键字实例的对象最深原型永远指向Object */ 666 instanceof Number // false new Number(666) instanceof Number // true new Number(666) instanceof Object // true '666' instanceof String // false new String('666') instanceof String // true new Object() instanceof Object // true [] instanceof Object // true [] instanceof Array // true new Date() instanceof Date // true new Date() instanceof Object // true

快速求和

              
  • 1
  • 2
  • 3
// eval能做的事真的太多了 var nums = [1, 2, 3, 4, 5, 6...] console.log('和:', eval(nums.join('+')))

简写判断

              
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
// 标准判断(推荐) if (a) { b() } // 简写 if (a) b() // 利用短路运算简写 a && b() // 或者(极力不推荐) var foo = 10 foo == 10 && doSomething() foo == 5 || doSomething()

with作用域

              
  • 1
  • 2
  • 3
  • 4
var obj = { name: 'xxx' } with(obj) { console.log(name) // 'xxx' }

复杂的流程控制

              
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
// 一种不太好的情况 if (a) { doSomethingA() } else if (b) { doSomethingB() } else if (c) { doSomethingC() } else if (d || e) { doSomethingDE() } else if (f) { doSomethingF() } //... // 可以用switch/case来代替 switch (true) { case a: doSomethingA() break case b: doSomethingB() break case c: doSomethingC() break case (d || e): doSomethingDE() break case f: doSomethingF() break default: doSomethingDefault() break }

本文于 2017/4/11 下午 发布在 Code 分类下,当前已被围观 1005 次

相关标签:Web开发软件工程Javascript

永久地址:https://surmon.me/article/33

版权声明:自由转载-署名-非商业性使用  |  Creative Commons BY-NC 3.0 CN