DOM訪問執行DOM交互的代碼比i通常的js代碼要慢。DOM交互是不可避免的,可是儘可能的減小。javascript
例如:php
考慮使用繼承機制css
對XMLHttpRequest設定超時時間html
考慮使用約定的數據來作大數據的處理,好比選擇xml或者jsonjava
目的:提升代碼可預測性和可維護性的方法是使用命名約定,這就意味着採用一致的方法來對變量和函數進行命名。ajax
變量名json
變量名包括全局變量,局部變量,類變量,函數參數小程序
構造函數(類)命名數組
首字母大寫,駝峯式命名。緩存
JS中沒有類,可是能夠用new調用構造函數:var man = new Person();
普通變量命名
首字母小寫,駝峯式命名,匈牙利命名
如:nCheckCount 表示整形的數值
匈牙利命名法
匈牙利命名法語法:變量名=類型+對象描述
類型指變量的類型
對象描述指對象名字全稱或名字的一部分,要求有明確含義,命名要容易記憶容易理解。
提示: 雖然JavaScript變量表面上沒有類型,可是JavaScript內部仍是會爲變量賦予相應的類型
JavaScript變量起名類型 |
變量命名前綴 |
舉例 |
Array 數組 |
a |
aList,aGroup |
Boolean 邏輯 |
b |
bChecked,bHasLogin |
Function 函數 |
f |
fGetHtml,fInit |
Integer 數字 |
n |
nPage,nTotal |
Object 對象 |
o |
oButton,oDate |
Regular Expression 正則 |
r |
rDomain,rEmail |
String 字符 |
s |
sName,sHtml |
其餘前綴規範
可根據團隊及項目須要增長
$:表示Jquery對象
例如:$Content,$Module,一種比較普遍的Jquery對象變量命名規範。
fn:表示函數
例如:fnGetName,fnSetAge;和上面函數的前綴略有不一樣,改用fn來代替,我的認爲fn可以更好的區分普通變量和函數變量。
例外狀況
以根據項目及團隊須要,設計出針對項目須要的前綴規範,從而達到團隊開發協做便利的目的。
做用域不大臨時變量能夠簡寫,好比:str,num,bol,obj,fun,arr。
循環變量能夠簡寫,好比:i,j,k等。
某些做爲不容許修改值的變量認爲是常量,所有字母都大寫。例如:COPYRIGHT,PI。常量能夠存在於函數中,也能夠存在於全局。必須採用全大寫的命名,且單詞以_分割,常量一般用於ajax請求url,和一些不會改變的數據。
函數命名
普通函數:首字母小寫,駝峯式命名,統一使用動詞或者動詞+名詞形式
例如:fnGetVersion(),fnSubmitForm(),fnInit();涉及返回邏輯值的函數可使用is,has,contains等表示邏輯的詞語代替動詞,例如:fnIsObject(),fnHasClass(),fnContainsElment()。
內部函數:使用_fn+動詞+名詞形式,內部函數必需在函數最後定義。
例如:
function fnGetNumber(nTotal) { if (nTotal < 100) { nTotal = 100; } return _fnAdd(nTotal); function _fnAdd(nNumber) { nNumber++; return nNumber; }}alert(fGetNumber(10)); //alert 101
對象方法與事件響應函數:對象方法命名使用fn+對象類名+動詞+名詞形式;
例如: fnAddressGetEmail(),
事件響應函數:fn+觸發事件對象名+事件名或者模塊名
例如:fnDivClick(),fnAddressSubmitButtonClick()
函數方法經常使用的動詞:
get 獲取/set 設置,
add 增長/remove 刪除create 建立/destory 移除
start 啓動/stop 中止open 打開/close 關閉,
read 讀取/write 寫入load 載入/save 保存,
create 建立/destroy 銷燬begin 開始/end 結束,
backup 備份/restore 恢復import 導入/export 導出,
split 分割/merge 合併inject 注入/extract 提取,
attach 附着/detach 脫離bind 綁定/separate 分離,
view 查看/browse 瀏覽edit 編輯/modify 修改,
select 選取/mark 標記copy 複製/paste 粘貼,
undo 撤銷/redo 重作insert 插入/delete 移除,
add 加入/append 添加clean 清理/clear 清除,
index 索引/sort 排序find 查找/search 搜索,
increase 增長/decrease 減小play 播放/pause 暫停,
launch 啓動/run 運行compile 編譯/execute 執行,
debug 調試/trace 跟蹤observe 觀察/listen 監聽,
build 構建/publish 發佈input 輸入/output 輸出,
encode 編碼/decode 解碼encrypt 加密/decrypt 解密,
compress 壓縮/decompress 解壓縮pack 打包/unpack 解包,
parse 解析/emit 生成connect 鏈接/disconnect 斷開,
send 發送/receive 接收download 下載/upload 上傳,
refresh 刷新/synchronize 同步update 更新/revert 復原,
lock 鎖定/unlock 解鎖check out 簽出/check in 簽入,
submit 提交/commit 交付push 推/pull 拉,
expand 展開/collapse 摺疊begin 起始/end 結束,
start 開始/finish 完成enter 進入/exit 退出,
abort 放棄/quit 離開obsolete 廢棄/depreciate 廢舊,
collect 收集/aggregate 彙集
變量命名例子
爲何須要這樣強制定義變量前綴?正式由於javascript是弱語言形成的。在定義大量變量的時候,咱們須要很明確的知道當前變量是什麼屬性,若是隻經過普通單詞,是很難區分的。
普通代碼
var checked = false;
var check = function() {
return true;
}
/**some code**/
if(check) {
//已經沒法很確切知道這裏是要用checked仍是check()從而致使邏輯錯誤
//do some thing
}
規範後代碼
var bChecked = false;
var fnCheck = function() {
return true;
}
/**some code**/
if(bChecked) {
// do some thing
}
if(fnCheck()) {
// do other thing
}
如何標明私有方法或私有屬性?
var person = {
getName: function () {
return this._getFirst() + ' ' + this._getLast();
},
_getFirst: function () {
//...
},
_getLast: function (){
//...
}
};
在這個例子中,getName()覺得這這是API的一個公開的方法,而_getFirst()和_getLast()意味着這是一個私有函數。儘管他們都是普通的公開方法,可是使用下劃線前綴的表示方法能夠提醒使用person對象的用戶,告訴他們這些方法在其餘地方不能確保必定可以正常工做,不能直接調用。
使用下劃線結尾來代表是私有變量,例如name_和getElements_()。
使用一個下劃線前綴來表示受保護屬性,使用兩個下劃線前綴來表示私有屬性。
爲代碼編寫註釋是很是重要的。一般人們在深刻思考一個問題時,會很是清楚這段代碼的工做原理。可是當過一週後再次回到該代碼時,可能會花上很長時間來回想起那段代碼究竟是幹什麼的。
公共組件維護者和各欄目WD都須要在文件頭部加上註釋說明:
/** *文件用途說明*做者姓名、聯繫方式(旺旺)*製做日期**/
大的模塊註釋方法:
//================// 代碼用途//================
小的註釋;
//代碼說明
註釋單獨一行,不要在代碼後的同一行內加註釋。例如:
//姓名var name = 「abc」; Vvar name =」abc」; //姓名 X
使用空格有助於改善代碼的可讀性和一致性。在撰寫英文文章時在逗號和區間範圍後面使用空格。
在javascript採用一樣的邏輯,可在列表表達式(等價於逗號)和語句結束(等價於完成一次「思考」)後面添加空格。
用處一:
用處二:
空格的另一個很好的用途是用來分隔全部的操做符和操做,這也就是意味着在 +, -, *, =, <, >, <=, >=, ===, !==, &&, ||, += 等以後使用空格:
例子:
//大量空格,而且使用一致,是的代碼可讀性更好
//容許在閱讀的時候不用一口氣讀下去
var d = 0, a = b +1;if ( a && b && c) { d = a % c; a += d;}
//反模式//缺乏空格或空格使用不一致,使得代碼比較混亂
var d= 0; a =b+1;if (a&& b&& c) {d=a %c; a+= d;}
生成API文檔的步驟:
簡單舉例:
/*** 翻轉一個字符串** @param {String} 輸入須要翻轉的字符串* @return {String} 翻轉後的字符串**/ var reverse = function (input) { //... return output;};
YUIDoc範例:
完整範例:本程序由一個文件(app.js)組成,該文件僅有一個模塊(myapp)。
app.js:
/*** 個人javascript應用程序* * @module myapp*/ //使用命名空間來定義一個空對象var MYAPP = {}; //定義一個包含兩個方法(sum()和multi())的math_stuff對象/*** @namespace MYAPP* class math_stuff*/ MYAPP.math_stuff = { /** * Sums two numbers * * @method sum * param {Number} 是第一個數 * param {Number} 是第二個數 * return {Number} 兩個輸入的總和 */ sum: function (a, b) { return a + b; }, /** * Multiplies two numbers * param {Number} 是第一個數 * param {Number} 是第二個數 * return {Number} 兩個輸入相乘後結果 */ multi: function (a, b) { return a * b; }};
@namespace:這裏用於命名包含以上對象的全局引用的名稱
@class:這裏有些命名不當,他實際意思是指對象或者構造函數
@method:定義對象中的方法和方法名
@param:列舉函數所使用的參數。其中將參數類型用大括號括起來,並在其後註釋參數名及描述。
@return:相似於@param,這裏用於描述返回值的,而且該方法沒有名稱。
@constructor:代表這個「類」其實是一個構造函數
@property和@type描述了對象的屬性。
2. 編寫API目的:
爲API編寫註釋不只僅是一中提供參考文檔的簡便方法,並且還有其餘用途——經過再次審查代碼,提升代碼質量。
在解決問題時寫出的解決方案僅僅是一個初稿。該解決方案能夠給出使人期待的輸出,可是該方案是不是最佳方案呢?改代碼是否可讀、易於理解、維護和升級呢?當您再次審視代碼時您將更加肯定代碼哪些部分能夠改進——如何使得代碼更容易繼續更新,移除一些不足之處等。它能夠極大地幫助您建立高質量的代碼。
除了三目運算,if,else等禁止簡寫
// 正確的書寫
if (true) {
alert(name);
}
console.log(name);
// 不推薦的書寫 if (true) alert(name); console.log(name);
// 不推薦的書寫 if (true) alert(name); console.log(name)
在須要以{}閉合的代碼段前增長換行,如:for if
// 沒有換行,小的代碼段沒法區分 if (wl && wl.length) { for (i = 0, l = wl.length; i < l; ++i) { p = wl[i]; type = Y.Lang.type(r[p]); if (s.hasOwnProperty(p)) { if (merge && type == 'object') { Y.mix(r[p], s[p]); } else if (ov || !(p in r)) { r[p] = s[p]; } } } }
// 有了換行,邏輯清楚多了 if (wl && wl.length) { for (i = 0, l = wl.length; i < l; ++i) { p = wl[i]; type = Y.Lang.type(r[p]); if (s.hasOwnProperty(p)) { // 處理merge邏輯 if (merge && type == 'object') { Y.mix(r[p], s[p]); } else if (ov || !(p in r)) { r[p] = s[p]; } } } }
換行能夠是空行,也能夠是註釋
使用Function進行類的定義,不推薦繼承,如需繼承採用成熟的類庫實現繼承
// 類的實現 function Person(name) { this.name = name; } Person.prototype.sayName = function() { alert(this.name); }; var me = new Person("Nicholas"); // 將this放到局部變量self function Persion(name, sex) { var self = this; self.name = name; self.sex = sex; }
平時我們寫代碼,基本都是小程序,真心用不上什麼繼承,並且繼承並非JS的擅長的語言特性,儘可能少用。若是非要使用的話,注意一點:
function A(){ //...}function B(){ //...}B.prototype = new A();B.prototype.constructor = B; //原則上,記得把這句話加上
繼承從原則上來說,別改變他的構造函數,不然這個繼承就顯得很彆扭了~
使用局部變量緩存反覆查找的對象(包括但不限於全局變量、dom查詢結果、做用域鏈較深的對象)
// 緩存對象
var getComment = function() {
var dom = $("#common-container"),// 緩存dom
appendTo = $.appendTo, // 緩存全局變量
data = this.json.data; // 緩存做用域鏈較深的對象
}
//當須要緩存this時必須使用self變量進行緩存// 緩存
thisfunction Row(name) {
var self = this;
self.name = name;
$(".row").click(function() {
self.getName();
});
}
self是一個保留字,不過用它也不要緊。在這裏,看我的愛好吧,能夠用_this, that, me等這些詞,都行,可是團隊開發的時候統一下比較好。
var isHotel = json.type == "hotel" ? true : false
這個是要引發注意的,好比:
a = b // 賦值(function(){ //....})() // 自執行函數
未加分號,結果被解析成
a = b(function(){//...})() //將b()()返回的結果賦值給a
var is_hotel;var isHotel;var ishotel;
if (isHotel) console.log(true)else console.log(false)
var json = eval(jsonText);
function() { var isHotel = 'true'; ....... var html = isHotel ? '<p>hotel</p>' : "";}
function() { var isHotel = 'true'; //....... 此處省略500行 return false;}