如何编写高质量代码

对于开发人员来说,编写高质量的代码是有很重要的意义的,特别是在团队协作里。本篇博文从前端开发的角度,总结出编写高质量前端代码的一些经验。前端开发涉及的主要语言包括html,css,js等。这里主要针对JS来介绍。

 

编码思维

1. 逻辑思维

当接到某个任务的时候,不要急于开始动手,而是先静下心来思考,理清这个任务要实现的功能,这个功能用在什么场景下,将来是否会复用,如果将来会变化,可能会怎样变化。要怎么设计利于功能的扩展和优化,可能会出现哪些问题,如何规避问题。这些都是在前期动笔前需要思考清楚的,不然到后面开发的时候可能会不停的修改,最终效率越来越低。一个功能有着良好的运行逻辑,才不会容易出错。当然如果时间不允许,或是只上一次就废弃的功能,此时效率可能会优先考虑。

通常专业的设计师,在设计网页的时候会使页面保持相同的风格,相似的模块同质性很高,这些在我们开发的时候,对复用性较高的代码定义成公共的模块或组件。甚至我们在接到设计稿的时候,对于差异较大但是功能类似的页面提出疑问,提醒视觉保持统一。

有良好的逻辑思维能力和丰富的工作经验能使我们想的更深更远。对写代码保持强烈的热情跟好奇心,多看多读,有些代码晦涩难懂,比如复杂的算法或是新的概念,没关系,第一次看了了解,第二次看了就熟悉,第三次可能就精通了,坚持学习和吸收新的知识,有助于我们更好的了解需要开发的功能,磨练自己的逻辑思维,增加解决问题的办法。

2. 优化思维

对于自己写过的代码持怀疑态度,追求完美的代码。何为完美,每个人的标准不一样。对于自己写过的代码,写完后想想整个的流程,是否还有值得优化的地方。尽量用最简洁的代码来实现,比如用三元运算符代替if语句,重复的代码提取成方法,重用的功能写成一个组件等等。对于写的不好的代码要有重构的勇气和信心。

在开发的过程中,还时时需要考虑页面的性能,选择性能最好的解决方案。比如JS少用全局变量,用完后及时销毁,合理使用闭包,避免频繁操作DOM节点,大量的计算等,HTML代码的SEO优化,样式的合理组织等,开发完后通过firebug或chrome自带的调试工具查看页面加载的速度,资源大小等,然后有针对性的优化。

3. 设计思维

作为一名前端开发,懂点设计的基础是很有必要的。前端的设计是指一个画面或元素,如何在不同的浏览器,不同的设备上被创建,显示,或删除。我们除了直接跟设计师打交道外,还直接面向用户,做好响应式的设计与开发,从用户的角度出发,客观的评价设计稿所传达的信息,是否体验最优,就是我们前端的设计思维。设计的思维,会直接影响我们写代码的结构。

 

JS代码规范

1.前端代码的组织结构和文件的命名

代码文件组织结构。前端文件主要包含HTML、CSS、JS等,对于文件组织,既要考虑结构清晰一目了然还要考虑代码的复用。基于这样的原则,惯用的做法是同类文件放在一起,并按模块划分文件结构。比如页面中公用的组件放到外部公共的components文件夹里,页面特有的组件则放到该模块对应的JS文件夹里,每个组件对应有html,js,css等内容。

代码文件的命名。名称需要表明文件对应的模块内容和文件的格式等。使用语义化的名字,避免使用数字来命名,比如a1.html,a2.html等。

2.命名规范

2.1变量

使用合理易于理解的英文变量名称,变量命名的风格统一,比如都用驼峰命名法,局部变量名尽量简短。NEJ里的规范,局部变用接口内局部变量或者传递的参数用_来量表示,如_type,_index等。对象外可访问的接口或者属性,用_$开头,_$$表示类对象等。

声明变量必须加上 var 关键字.当你没有写 var, 变量就会暴露在全局上下文中, 这样很可能会和现有变量冲突。变量需先声明后使用,防止变量提升。

另外常量名字都用大写。

2.2方法

JS面向对象开发中公有接口命名首字母为大写,私有接口命名首字母小写。事件的命名用动词+名词+动词的方式,方法名具有语义化,尽量完整。如:onExchange,doExchange,cbExchange等。逻辑操作符 || 和 && 可被用来返回布尔值,简化代码。

3.代码注释

代码加上合理的注释,提高可读性。例如对于某个功能的简介,或者变量的特殊含义和用处。每个JS文件头部说明下作者,日期,文件介绍等。

/**
* KJ-13989 组团买好货
* author AAA
* 2015-12-09 
*/
/**
 * 接口函数的说明
 * 参数说明
 */
/**
  * 空闲控制 返回函数连续调用时,空闲时间必须大于或等于 wait,func 才会执行
  *
  * @param {function} func    传入函数
  * @param {number}  wait    表示时间窗口的间隔
  * @param {boolean} immediate  设置为ture时,调用触发于开始边界而不是结束边界
  * @return {function}       返回客户调用函数
  */

当你写注释时一定要注意:不要写你的代码都干了些什么,而要写你的代码为什么要这么写,背后的考量是什么。对于文件的修改,也可以在注释里加上相关的任务号。

4.语句结束时添加分号

记得语句结束时使用分号。如果仅依靠语句间的隐式分隔, 有时会很麻烦。而且添加分号也利于代码的理解。

5.不要在块内声明一个函数,使用函数表达式来定义函数

不要写成:

if (x) {
  function foo() {}
}

虽然很多 JS 引擎都支持块内声明函数, 但它不属于 ECMAScript 规范 (见 ECMA-262, 第13和14条)。 各个浏览器的实现相互不兼容, 有些也与未来 ECMAScript 草案相违背。ECMAScript 只允许在脚本的根语句或函数中声明函数。 如果确实需要在块中定义函数, 建议使用函数表达式来初始化变量:

if (x) {
  var foo = function() {}
}

6.避免定义全局变量或函数

函数可以采用匿名函数包裹的方法实现封装,如

(function(){
    //do some thing
})()

全局变量可以通过定义全局对象变量来存储,像在ftl页面的JS中定义ftl值的时候,可以统一写成:

var configInfos ={
        remindType:${remindType!2},
        totalPoint:${pointTotalCount!0},
        isSigned:"${isSigned?string('yes','no')}"
    }

而后通过configInfos.remindType获取到remindType值。这样可以减少全局变量的个数,避免变量冲突。

7.使用单引号定义字符串。

ftl文件中用双引号,JS中用单引号。

8.使用简化的编码方式。

如对象和数组的声明,三元操作符等。

var a = [],obj={};

9.避免使用with语句。

该语句在设计上就有缺陷,在ES5和ES6上也存在潜在兼容问题。对性能也有很大影响。

10.避免使用eval。

存在潜在安全问题,在需要使用eval的场景中应当尽量使用其它方法代替。

11.事件处理和业务逻辑分离,数据和代码逻辑分离。

现在使用的RegularJs框架正是实现了数据与代码逻辑的分离。

12.结构样式与逻辑分离

CSS样式分离,将多个样式放置在class中后控制class的增删,通过挂靠样式名来改变样式。避免在JS中对元素操作大量的style来改变样式。

_e._$addClassName(this.__passWord,'u-ipt-login-active');

13.合理定义交互元素的样式名

在JS中,可以通过获取元素的className,id,或元素名来操作DOM节点。如果是页面上固定的节点,则可以通过给元素挂靠'ztag','j-flag'等样式名。这些名字不需要带任何样式。避免用大量的id来获取元素。如果是通过判断来显示的元素,则可以通过ID来获取。

pro.__getNodes = function(){
        var _node = _e._$getByClassName(document.body,'ztag'),i=0;
        this.__aboutWrap = _node[i++];
        this.__goodsDescWrap = _node[i++];
        this.__fixedBtn = _node[i++];
        this.__payBtn = _node[i++];
    };

14.代码格式化

15.理解 JavaScript 的定义域和定义域提升,提前声明变量

在 JavaScript 中变量和方法定义会自动提升到执行之前。JavaScript 只有 function 级的定义域,而无其他很多编程语言中的块定义域,所以使得你在某一function 内的某语句和循环体中定义了一个变量,此变量可作用于整个 function 内,而不仅仅是在此语句或循环体中,因为它们的声明被 JavaScript 自动提升了。所以一般在函数开头先声明好变量。避免变量在定义前被使用,导致报错。

16.合理使用AJAX技术

明确AJAX技术的使用场景,在AJAX过程中做好用户的交互,如禁用按钮避免重复触发、显示加载进度条等。

17.内存回收

全局对象或对象的属性使用完后,将值设为null或undefined,或者某个实例化的组件,使用后及时解除引用(recycle或destroy方法),解除已经不需要的事件监听(delEvent),不要在函数内返回外部不需要的对象等。这些操作利于浏览器的回收程序执行时能回收其占用的内存。

18.使用高性能的变量或属性值的读取方式

在使用变量和属性时,如果需要多次调用,则定义成局部变量再使用。最简单的例如for循环中,可以将变量或属性缓存起来:

for(var i=0,len=number.length;i<len;i++){}

变量涉及作用域链查找的过程,属性涉及原型链查找的过程,定义成局部变量可以节约查找的时间。

19.高效的DOM操作

DOM操作对性能最大的影响是因为它导致了浏览器的重排和重绘。

使用文档片段:创建一个文档片段(documentFragment),并在此片段上进行DOM操作,操作完成后将它附加在页面中,这样重排和重绘的操作就只有附加了。

通过设置DOM元素额的display样式为none来隐藏元素:通过隐藏DOM达到在页面中移除元素的效果,这样重排和重绘的操作就只有隐藏和显示了。

克隆DOM元素到内存中:将元素克隆一份然后在内存中操作DOM,操作完之后替换,这样重排和重绘的操作就只有替换了。当元素中有事件绑定时,cloneNode会把事件移除掉,不适合用这种方法来操作。

设置具有动画效果的DOM元素的position为fixed或absolute:使元素脱离页面布局流,从而避免页面频繁的重排。

谨慎取得DOM元素的布局信息(offsetHeight等):如果需要重复使用这些信息可以先缓存起来。

使用事件委托来绑定事件:利用事件冒泡机制,只在父元素上绑定事件,然后在事件处理函数中根据传入的参数判断事件的源元素,然后针对不同的源元素做不同的处理。这样避免了给多个子元素绑定事件。

20.增加容错处理

例如给变量或属性设置默认值,对某段代码使用try,catch操作。

21.代码注意安全性

常见的Web前端攻击方式有XSS Cross Site Scripting 跨站点脚本攻击,CSRF Cross Site Request Forgery 跨站请求伪造,界面操作劫持等。我们需要注意的是不轻信任何用户输入的内容,针对用户输入的内容进行HTML编码、JavaScript编码、CSS编码、URL编码等。对用户表单提交的数据做完整的验证。

22.移动端开发注意点

使用流式布局。使用合适的图片显示兼容方案。使用移动平台特有事件处理如手势操作。增加链接按钮的可操作区域,如安卓开发规范中保证这些控件的高度至少有48px间隔至少有32px等。

23.代码检查,code review

24.ftl里代码优化

ftl里避免在JS中填充大量的数据,尤其是像列表数据,不利于优化。如果确实需要,在JS获得数据后删除该节点。

 

其他注意点

1.提前设计

提前规划设计好,从全局角度规划代码的结构。保证代码精简,写完某个功能后重新思考下整个流程,是否可以优化,方向有没有写错。

我记得刚开始写代码的时候,某个功能写到某一步的时候,发现写不下去了,这个时候只能重新换个思路,推倒之前的代码重新写。这就是没有提前规划好思路,急于下笔,导致浪费了很多时间。

2.前端代码重构注意事项

重构前一定要预估风险,如果没有足够的自动化测试,最好是先完善自动化测试代码。

重构的目的和范围要明确,切忌盲目修改,前端代码的重构目的主要是提高代码的可维护性、可读性和性能。

最好是先易后难,循序渐进。首先修改诸如命名、格式等不涉及具体逻辑的内容,然后考虑模块化和性能提升等具体逻辑相关的内容。

重构过程中要持续测试,在多个浏览器中测试,确保重构一部分功能正确,切忌在大量重构后再进行测试,因为大量重构后基本很难记得重构的逻辑,也就有可能遗漏部分测试用例。

如果是提升性能,要事先检测网站的整体性能并量化,找出性能瓶颈,重构过程中要持续监控性能,并对比性能提升的效果。

3.快速编写页面

拿到设计稿后,规划好结构,先写完html代码,最后再补充完整的样式,这样效率最高。边写边调是很浪费时间的。

 

参考文章:

http://itwap.net/ArticleContent.aspx?id=35

http://www.css88.com/archives/5366

posted @ 2016-01-12 16:43  ZRainna  阅读(2303)  评论(0编辑  收藏  举报