代码改变世界

《编写高质量代码188个建议》读书笔记

2014-05-05 22:43  臭小子1983  阅读(298)  评论(0编辑  收藏  举报

第一章  JavaScript语言基础

一、代码的执行速度决定的因素是:

  1、代码量少,运行速度不一定快  2、代码量多,速度也不一定慢   

 

建议1:警惕Unicode代码

  javascript代码每个字符都两字节,这样函数名和变量名都可以使用中文来命名

 1 <script>
 2     var 人名 = "张三";
 3     console.log(人名);
 4 
 5     function 技术(开发){
 6         console.log(开发);
 7     }
 8 
 9     技术("哈哈");
10 </script>

 

建议2:辨析js语句中的词、句和段

 

 

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

  定义全局变量的3种方式:

  1、在函数外面直接执行var 语句。 var f = 'value';

  2、直接添加到window对象上。   window.f = 'value';

  3、不使用var声明的变量。    f = value

 

避免全局变量的方法:

 1 // 没有一个全局变量
 2 (function(w){
 3     function getColor(){
 4         // 执行代码
 5     }
 6 
 7     getColor();
 8 })(window);
 9 
10 // 使用命名空间
11 var RRG = RRG || {};
12 RRG.DOM = {
13     // 处理DOM
14 }
15 
16 RRG.Event = {
17     // 处理Event
18 }

 

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

  1、防止浮点溢出:

    二进制的浮点不能正确的处理十进制的小数, num = 0.1 + 0.2;    // num不等于0.3

    整数运算是精确的所以可以改写成:  num = (1+2)/10;    // 返回0.3

 

  2、正确测数据类型:

    js有六个类型:number、string、boolean、object、function、undefined

 

    typeof null返回"object",而不是null、解决方法:

1 function type(o){
2     return (o === null) ? "null" : typeof o;
3 }

 

  3、避免误用parseInt

    parseInt是将字符串转成整型

    parseInt("123abc");  // 123

    parseInt("1.73");    // 1

    parseInt(".73");      // NAN

 

    parseInt("010");  // 字符串第一个字符为0以八进制来求值,返回8  parseInt("0x10");  // 十六进制,返回16

    parseInt("08");   // IE内核下返回0,因为以八进制

    解决方法:

    parseInt("08", 10); // 返回8

 

  4、正确处理js特殊值

    1、NaN:NaN是一个特殊的数量值,它不表示一个数字,尽管下面表达式返回true。

      type NaN === "number";  // true;

      NaN === NaN    // false

      isNaN(NaN);     // true;

    

    2、Infinity:表示无穷大

 

    3、null和undefinded

      五种基本类型:string、number、boolean、null和undefined

      null:表示一个对象为空或不存在对象引用

      undefined:当一个变量没有值的时候会返回undefined

      console.log(null == undefined);  // true;
      console.log(null === undefined);  // false;

 

建议5:谨慎使用运算符

  1、用===,不用==

    0 == "0";    // true;

    0 === "0";    // false

 

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

  1、加小括号:

    if(a+b > b && a-b < c || a>b>c) 改写成 if( (a+b > b) && (a-b < c) || (a>b>c))

 

  2、使用if分解

    var a.b  = new c(a.d ? a.e(1) : a.f(1)) 

    改写成:

    var a.b;

    if(a.d){

      a.b = new c(a.e(1));

    }

    else{

      a.b = new c(a.f(1));

    }

 

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

  当有大量离散值需要测试时,switch要比if快的多

 1 <script>
 2     switch(value){
 3         case 0:
 4             return result0;
 5             break;
 6         case 1:
 7             return result1;
 8             break;
 9         case 2:
10             return result2;
11             break;
12         case 3:
13             return result3;
14             break;
15         default: ;
16     }
17 
18     // 可以改写成
19     var arr = [result0, result1, result2, result3];
20     return arr[value];
21 </script>

 

建议33:优化循环结构

  1、结构优化

  循环一般与条件判断句语混在一起

 1 var a = true;
 2 for(var i=0; i<10000; i++){
 3     if(a){
 4         // code...
 5     }
 6 }
 7 
 8 // 改写成
 9 if(a){
10     for(var i=0; i<10000; i++){
11         // code...
12     }
13 }

 

  2、避免不必要的重复操作

 1 <script>
 2 for(var i=0; i<10000; i++){
 3     var arr = [1, 2, 3, 4, 5, 6];
 4     alert(arr);
 5 }
 6     
 7 // 改写成
 8 var arr = [1, 2, 3, 4, 5, 6];
 9 for(var i=0; i<10000; i++){    
10     alert(arr);
11 }
12 </script>

 

  3、妥善定义循环变量

1 <script>
2 var s = 0;
3 for(var i= 0, s=20; i< s; i++){
4     // code...
5 }
6 </script>

 

 

第二章  字符串、正则表达式和数组

  合并、分解、搜索、遍历以及其它的字符串处理方式

 

建议36:获取字符有多少字节

  字符有单字节和双字节,charCodeAt > 255 为双字节,也就是汉字为双字符字母和数字和特殊符号都为单字节

 1 <script>
 2     var str = "soaear";
 3     var n = 0;
 4 
 5     for(var i=0; i<str.length; i++){
 6         if(str.charCodeAt(i) > 255){
 7             n += 2;
 8         }
 9         else{
10             n++;
11         }
12     }
13 
14     // 使用正则
15     for(var i=0; i<str.length; i++){
16         var t = str.charAt(i);
17         if(/^[\u0000-\u00ff]$/.test(t)){
18             n++;
19         }
20         else{
21             n += 2;
22         }
23     }
24 </script>

 

 建议37:推荐使用replace()

    var b = s.replace("html", "htm");    // 将所有的html字符替换成htm

  另外还有

  search():搜索所在的位置,如果没有返回-1

  test():如果存在返回true,否则返回false

  match():如果存在以数组返回,否则返回null

 

 建议37:使用splice删除数组

1 <script>
2     var arr = [1, 2, 3, 4, 5, 6];
3 
4     // 参数1:开始位置   参数2:结束位置    参数3:要替换的字符
5     var ss = arr.splice(3,5);       // 返回 [4, 5]
6     console.log(ss);
7 </script>

 

 建议38:数组的排序使用sort

 1 <script>
 2     var arr = [200,1,20,3,19, 30,12,359, 402, 33, 47,3595];
 3 
 4     // 从大到小排序
 5     arr.sort(function(a,b){
 6         return a - b;       // 从小到大排序
 7     })
 8     console.log(arr);
 9 
10     // 奇偶排序
11     arr.sort(function(a, b){
12         a = a % 2;
13         b = b % 2;
14         if(a == 0) { return -1 }
15         if(b == 0) { return 1 }
16     })
17     console.log(arr);       // 返回[12, 20, 30, 200, 402, 1, 3, 47, 3595, 359, 19, 33] 
18 </script>

 

第五章  DOM编程

  减少ECMAScript对DOM的操作

 

建议107:应清理HTML DOM流程

  HTML DOM文档加载是按顺序执行的,与浏览器的渲染方式有关系,一般浏览器的渲染操作:

  1、解析HTML结构

  2、加载外部脚本和样式

  3、解析并执行脚本

  4、构造DOM模型

  5、加载外部图片等外部文件

  6、页面加载完成

 

建议108:谨慎访问DOM

  修改一个DOM元素会消耗性能,因为会导致页面的重排重绘,特别是循环时访问DOM元素

 1 <script>
 2     for(var i= 0, len=1000; i<len; i++){
 3         document.getElementById("box").innerHTML = i;
 4     }
 5     
 6     // 可以改写成
 7     var conut = 0;
 8     for(var i= 0,len=1000; i<len; i++){
 9         conut += i;
10     }
11     document.getElementById("box").innerHTML = conut;    
12 </script>

 

建议109:比较innerHTML与DOM创建元素方法createElement

  innerHTML要比DOM创建元素的方法要快一些

 

建议111:克隆节点比创建节点更好

  element.cloneNode()代替document.createElement()

  克隆比较有效率,但提高并不太多

 

建议113:用局部变量访问集合元素

 1 <script>
 2     // 比较慢的方法
 3     function collection(){
 4         var coll = document.getElementsByTagName("div"), len = coll.length, name = "";
 5         for(var i=0; i<len; i++){
 6             name = document.getElementsByTagName("div")[i].nodeName;
 7             name = document.getElementsByTagName("div")[i].nodeType;
 8             name = document.getElementsByTagName("div")[i].tagName;
 9         }
10         return name;
11     }
12 
13     // 较快的方法
14     function collection(){
15         var coll = document.getElementsByTagName("div"), len = coll.length, name = "";
16         for(var i=0; i<len; i++){
17             name = coll[i].nodeName;
18             name = coll[i].nodeType;
19             name = coll[i].tagName;
20         }
21         return name;
22     }
23 
24     // 最快的方法
25     function collection(){
26         var coll = document.getElementsByTagName("div"), len = coll.length, name = "", el = null;
27         for(var i=0; i<len; i++){
28             el = coll[i];
29             name = el.nodeName;
30             name = el.nodeType;
31             name = el.tagName;
32         }
33         return name;
34     }
35 </script>

 

建议117:减少重绘、重排

  改变了宽度、高度、定位边框、内边距等,都会使元素重排.

  改变颜色不会影响到宽、高这样只会完成重绘

  一、发生重排:

    1、添加、删除可见的DOM元素

    2、元素的位置改变

    3、元素的尺寸改变,(边距、填充、边框宽度、宽度高度)

    4、内容的改变,如图片或文字所被另一个图片文字所代替

    5、最初的页面渲染

    6、浏览器窗口尺寸的改变

 

建议118:DOM将事件拖管

 

第六章  客户端编程

建议123:比较IE和W3C事件流

  IE支持冒泡事件,非IE支持的是捕获事件.

  <p onclick="aa()"></p>

  冒泡事件为:事流程流为p-body-html-document-window

  捕获事件为:window-document-html-body-p

 

建议127:妥善使用DOMContentOnloaded事件

  load事件是需要等到页面中的图片全部都加载完成后才会触发,而DOMContentOnloaded事件是DOM文档加载完成后就会被触发

 1 <img src="http://c.hiphotos.baidu.com/image/pic/item/9f510fb30f2442a7abf0bc2dd343ad4bd01302bf.jpg">
 2 
 3 <script>
 4     window.addEventListener("load", function(){
 5         console.log("页面初始化完成");
 6     }, false);
 7 
 8     window.addEventListener("DOMContentLoaded", function(){
 9         console.log("DOM树已加载完成");
10     }, false);
11 </script>

 

建议129:自定义事件

 

第七章  数据交互和存储

 

建议147:ajax性能向导

  有两种方法避免发出一个不必要的请求:

  1、在服务器,设置HTTP头,确保返回的报文将被缓存在浏览器中.

  2、在客户端,对于本地缓存已获取的数据,不要多次请求同一数据.

  Expires头设置:

 

建议149:警惕基于DOM的跨域侵入

  1、基于DOM跨域脚本编制

  XSS跨站脚本攻击,攻击者向web页面插入恶意代码,然后提交给服务器,

 

  2、通过URL重定向钓鱼

    网络钓鱼表示通过欺骗手段窃取用户个人信息,常见的是通过URL重定向钓鱼漏洞行为方式

    

  3、客户端Javascript cookie引用

 

  4、javascript脚本劫持