本文主要從以下幾個方面串燒如何優化我們的JavaScript代碼——
1>變量類型和變量聲明
2>等號(==)和非等號(!=)
全等號(===)和非全等號(!==)
3>邏輯與(&&)運算和邏輯或(||)運算
4>函數聲明 vs 函數表達式
5>命名空間
6>分號和空格
主要是從讓代碼更加簡潔、更加美觀的角度去思考總結在書寫JavaScript代碼需要注意的要點——
1 (function($){ 2 3 var namespace = {}; 4 5 namespace.basevar = function () { 6 /** 7 * 基本數據類型:number、字符串、布爾值、null和undefined 8 */ 9 console.log(typeof 89.6); //number 10 console.log(typeof 'xxx'); //string 11 console.log(typeof true); //boolean 12 console.log(typeof null); //object,這個值來的比較詭異 13 console.log(typeof undefined); //undefined 14 /** 15 * 其余的類型我們均可以以對象的類型去看待,可能比較歧義的地方就是字符串string和數組array了, 16 * 需要記住,在js中任意字符串均屬於string類型,任何數組均屬於object類型 17 * 當我們需要創建數組和對象的時候,避免使用new Object和new Array方式,我們用{}和[]來代替 18 */ 19 }; 20 21 function test() { 22 /** 23 * 在JavaScript中,我們不提倡在變量第一次使用時才被聲明,在函數的開始部分聲明所有變量,是一個非常好的編程實踐。 24 * 在這里,介紹一下單變量的聲明方式,大叔的博客介紹的很詳細,其好處在於 25 * 1>提供了一個單一的地方去尋找功能所需要的所有局部變量 26 * 2>防止變量在定義之前使用的邏輯錯誤 27 * 3>少代碼(類型和傳值單線完成) 28 */ 29 var obj = {}; //初始化變量的同時初始化值,這是一個好的編程實踐,當我們再次看到代碼的時候,我們就知道這些變量的大致用途 30 var array = []; 31 var xxx = null; 32 var yyy = undefined; 33 //我們可以替換成為—— 34 var obj = {}, 35 array = [], 36 xxx = null, 37 yyy = undefined; 38 39 //當我們去判斷一個對象真的是對象時,首先需要先排除它並不是null,是因為typeof null的值是object 40 console.log(typeof null); //object 41 42 if (array && typeof array === 'object') { 43 //數組是一個對象,不要忘記了這點 44 //但同時,對象也是對象,我們再嚴格去判斷數組的時候,可以這樣寫—— 45 if (array && typeof array === 'object' && array.constructor === Array) { 46 alert('array is a Array'); 47 } 48 alert('array is a Object'); 49 } 50 51 //當判斷某一個值真的是null的時候,我們直接用以下方式最為簡潔 52 xxx === null && console.log(xxx); //null 53 //當然我們去判斷undefined值的時候,同樣如此—— 54 yyy === undefined && console.log(yyy); 55 56 //關於相等或不相等的判斷,是一個令人頭痛的事情,因為規則多而雜。以下摘自《JavaScript高級程序設計-第3版》 57 /** 58 * 我們先理清一個概念: 59 * ==和!= :等號和非等號 60 * ===和!== :全等號和非全等號 61 * 先看等號==和非等號!=的運算規則: 62 * 1>如果一個運算數是Boolean值,在檢查相等性之前,把它轉換成數字值。false轉換為0,true轉換為1。 63 * true == 1; //true 64 * false == 0; //true 65 * true == 2; //false 66 * 2>如果一個運算數是字符串,另一個是數字,在檢查相等性之前,要嘗試把字符串轉換成數字。 67 * '5' == 5; //true 68 * 3>如果一個運算數是對象,另一個是字符串,在檢查相等性之前,要嘗試把對象轉換成字符串(調用toString()方法)。 69 * //任意一個對象的toString()方法都返回一個字符串"[object Object]",緊接着就拿這個字符串和比對字符串進行比較了 70 * //確實有些暈乎了,JavaScript中的對象都可以理解為鍵值對的集合,我們所比較的應該是該對象里的某一個屬性值和這個字符串是否相等 71 * 4>如果一個運算數是對象,另一個是數字,在檢查相等性之前,要嘗試把對象轉換為數字。 72 * 5>值null和undefined相等。 73 * null == undefined; //true 74 * 6>在檢查相等性時,不能把null和undefined轉換成其他值。 75 * undefined == 0; //false 76 * null == 0; //false 77 * 7>如果某個運算數是NaN,等號將返回false,非等號將返回true。NaN不等於NaN 78 * NaN == 5 //false 79 * NaN != 5 //true 80 * NaN == NaN //false 81 * NaN == 'NaN' //false 82 * 8>如果兩個運算數都是對象,那么比較的是它們的引用值。如果兩個運算數指向同一個對象,那么等號返回true。 83 */ 84 /** 85 * 對於全等號和非全等號,和等號和非等號都差不多,只不過它們在檢查相等性前,不執行類型轉換。 86 * 只有在無類型轉換運算數就相等的情況下,才返回true。 87 * 我們建議不要使用等號==和非等號!=進行判斷,相反的,始終使用全等號===和非全等號!==,這會提高我們代碼的閱讀性。 88 * 如果我們希望使用強制類型轉換,那么就使用簡易格式,如: 89 * if (foo) {...} //而不是if (foo != 0) {...} 90 * if (!foo) {...} //而不是if (foo == 0) {...} 91 */ 92 /** 93 * 談完了等性運算符,我們常常把等性運算與邏輯與'&&'運算及邏輯或'||'運算結合在一起進行應用, 94 * 來看看||和&&用在什么場景: 95 * 1>||運算符可以用來填充默認值 96 * var str = str || ''; //毫無疑問,提高了程序的健壯性 97 * 2>&&運算符可以避免錯誤 98 * //當obj沒有equipment屬性或者obj.equipment === ''(null) 的時候,后面語句也就不執行了, 99 * //防止直接訪問model屬性時,產生的錯誤 100 * obj.equipment && obj.equipment.model 101 * //這句代碼是老相識了,簡單的理解它為單線程的if判斷,讓代碼看起來比較簡潔和優雅 102 * $.browser.msie && $.browser.version <= 6 && ... 103 */ 104 } //test函數結束 105 /** 106 * 在上面呢,我們用的是函數聲明的方式定義函數,function語句在解析時會發生被提升的情況(講的不是很官方,不過,卻非常好理解)。 107 * 這意味着不管function在哪里,它都會被移動到被定義時所在作用域的頂層。這放寬了函數必須先聲明后使用的要求。 108 * 不過,它在一定程度上會導致混亂。當我們的代碼非常之多的時候,維護起來就有些難了。提倡使用函數表達式的形式 109 * var foo = function foo() {...}; //而不是function foo() {...} 110 * //至於為什么function右邊為什么再次聲明了函數名foo,debug一下,看看調用棧就知道了。 111 * //當然,實際編寫代碼的時候,沒有必要加 112 * 最主要的是,當我們采用的是函數表達式的方式定義函數的時候,我們可以讓這個函數對象賦值進一個命名空間, 113 * 讓每一個對象都有自己的命名空間,可以讓我們很容易使用對象去管理代碼。當然,這里的命名空間僅僅是一個對象而已。 114 * 命名空間再結合閉包(模塊模式)的使用,不僅能夠減少全局變量的污染,更加提高了代碼的封裝性。 115 */ 116 117 /** 118 * 這里要注意的是,如果一個return語句返回一個值,這個值表達式的開始部分必須和return在同一行上。 119 */ 120 namespace.block = function () { 121 // return //undefined 122 // { 123 // num : 100 124 // }; 125 return { //object 126 num : 100 127 }; 128 /** 129 * 另外—— 130 * 1>我們最好始終要用一對花括號來包住我們的代碼塊。 131 * 2>'{' 放在一行的結尾,而不是下一行的開頭 132 */ 133 }; 134 /** 135 * 對於分號,JSLint期望除了for、function、if、switch、try和while之外的每一個語句后面都跟着分號。 136 */ 137 /** 138 * 對於空格,大叔博客總結得到位,拷貝下—— 139 * 1>for循環分號分開后的的部分:如for (var i = 0; i < 10; i += 1) {...} 140 * 2>for循環中初始化的多變量(i和max):for (var i = 0, max = 10; i < max; i += 1) {...} 141 * 3>分隔數組項的逗號的后面:var a = [1, 2, 3]; 142 * 4>對象屬性逗號的后面以及分隔屬性名和屬性值的冒號的后面:var o = {a: 1, b: 2}; 143 * 5>限定函數參數:myFunc(a, b, c) 144 * 6>函數聲明的花括號的前面:function myFunc() {} 145 * 7>匿名函數表達式function的后面:var myFunc = function () {}; 146 * 8>操作符和操作對象之間,這意味着在+, -, *, =, <, >, <=, >=, ===, !==, &&, ||, +=等前后都需要空格。 147 * 9>if-else語句、循環、對象字面量的左花括號的前面 148 * 10>else或while之間的右花括號 149 */ 150 151 /** 152 * -------------------------------------------------------------------- 153 * 參考文章—— 154 * 《JavaScript語言精粹》—— 155 * 第3章——對象 156 * 第9章——代碼風格 157 * 第10章——優美的特性 158 * 附錄A——糟粕 159 * 附錄B——雞肋 160 * 附錄C——JSLint 161 * 《JavaScript高級程序設計-第3版》—— 162 * 第2章——ECMAScript基礎 163 * 湯姆大叔的博客—— 164 * 深入理解JavaScript系列(1):編寫高質量JavaScript代碼的基本要點 165 * 深入理解JavaScript系列(2):揭秘命名函數表達式 166 * -------------------------------------------------------------------- 167 */ 168 169 })(jQuery);