《編寫可維護(hù)的javascript》讀書筆記(中)——編程實(shí)踐

二灯帮、編程實(shí)踐

1每强、UI松耦合

第一秉沼、將css從javascript中抽離(要改變dom樣式數(shù)據(jù),應(yīng)該去操作dom的class名而非dom的style屬性辕狰,后續(xù)要修改此樣式只需到對(duì)應(yīng)的css文件中修改而不用修改js文件)改备;

第二、將javascript從HTML中抽離蔓倍,比如下面的寫法是不好的

<!-- 不好的寫法 -->
<input type="button" onclick="doSomething" />

js應(yīng)該放在外部文件中悬钳,方便維護(hù);

第三偶翅、避免使用css表達(dá)式默勾,嚴(yán)重影響頁面性能;

第四聚谁、將HTML從javascript中抽離母剥,比如你要?jiǎng)討B(tài)生成一個(gè)N行4列的表格,表頭和tbody可以寫死在頁面里,表體你可能會(huì)這樣循環(huán)生成

  // 不好的寫法
    var str=""; for (var i = 0; i < data.length; i++) {
        str+="<tr><td>"+ data[i].字段一 +"</td><td>"+ data[i].字段二 +
             "</td><td>"+ data[i].字段三 +"</td><td>"+ data[i].字段四 +"</td></tr>";
    };
    $("tbody").html(str);

假如現(xiàn)在要增加一個(gè)字段媳搪,將表格的列數(shù)增加到5列铭段,你要先到html頁面修改表頭骤宣,又要到j(luò)s里修改js文件……所以秦爆,盡量將html從js中分離出去是好的做法,可以在html里面寫一個(gè)模板憔披,通過js獲取模板內(nèi)容替換變量生成html填充到tbody里面等限。

2、避免使用全局變量

命名本身就是一件比較困難的事芬膝,如果大量使用全局變量望门,隨著代碼量不斷增加,命名沖突概率隨之增高锰霜,程序維護(hù)成本也隨著增高筹误。

3、事件處理

規(guī)則1:隔離應(yīng)用邏輯

什么意思呢癣缅?好比電腦要關(guān)機(jī)厨剪,有個(gè)關(guān)機(jī)的程序放在那里,你可以按關(guān)機(jī)按鈕觸發(fā)關(guān)機(jī)程序友存,也可以點(diǎn)開始菜單再選擇關(guān)機(jī)去觸發(fā)關(guān)機(jī)程序祷膳,這個(gè)關(guān)機(jī)程序是獨(dú)立出來的。代碼也是如此屡立,當(dāng)點(diǎn)擊按鈕A或按鈕B要做的操作是一樣的時(shí)候直晨,應(yīng)該將操作獨(dú)立寫成一個(gè)函數(shù),這就是應(yīng)用邏輯隔離膨俐。

規(guī)則2:不要分發(fā)事件對(duì)象

先看一段代碼

function handleClick(event){ var popup = document.getElementById("popup");
        popup.style.left = event.clientX + "px";
        popup.style.top= event.clientY + "px";
        popup.className = "reveal";
    }

    document.getElementById("demo").onclick=function(event){
        handleClick(event);
    };

上面這段代碼中勇皇,event被無節(jié)制地分發(fā),它從事件處理函數(shù)中傳入handClick()焚刺,event對(duì)象上包含很多信息敛摘,而handClick函數(shù)內(nèi)只用到了其中2個(gè)而已,該函數(shù)并沒有標(biāo)明哪些數(shù)據(jù)是必要的檩坚,假如此時(shí)你也要調(diào)用這個(gè)方法着撩,你必須創(chuàng)建一個(gè)evnet對(duì)象并將它作為參數(shù)傳入,而你依然不知道這個(gè)方法使用了哪些信息匾委,我們可以做如下修改

function handleClick(x,y){ var popup = document.getElementById("popup");
        popup.style.left = x + "px";
        popup.style.top = y + "px";
        popup.className = "reveal";
    }

    document.getElementById("demo").onclick=function(event){
        handleClick(event.clientX,event.clientY);
    };

4拖叙、避免“空比較”

有時(shí)候我們需要檢測(cè)函數(shù)的某個(gè)參數(shù)是否存在,可能會(huì)通過判斷這個(gè)參數(shù)是否等于null來判斷出參數(shù)是否存在

var comtroller = {
    process:function(items){ if(items!==null){  // 不好的寫法
 items.sort(); // 執(zhí)行一些邏輯
 }
    }
}

這段代碼中赂乐,process方法顯然希望items是一個(gè)數(shù)組薯鳍,然后當(dāng)items的值為1時(shí),不等于null,依然進(jìn)入if語句內(nèi)了挖滤,執(zhí)行到items.sort()就報(bào)錯(cuò)了

5崩溪、檢測(cè)原始值(string、number斩松、boolean伶唯、undefined、null)惧盹,typeof就夠了

6乳幸、檢測(cè)引用值(Object、Array钧椰、Date粹断、Error),引用值也稱做對(duì)象嫡霞,一般情況下使用instanceof來檢測(cè)這個(gè)對(duì)象的構(gòu)造器是否為對(duì)應(yīng)的值即可瓶埋,當(dāng)跨域檢測(cè)時(shí),用instanceof檢測(cè)數(shù)組將失敗诊沪,解決方案是將該對(duì)象的原型調(diào)用toString()方法养筒,判斷返回的字符串是否等于[object Array]來得出結(jié)論:

  // 判斷value是否為數(shù)組
    function isArray(value){ 
        return Object.prototype.toString.call(value)==="[object Array]";
    }

7、檢測(cè)函數(shù) 用typeof即可娄徊,可以跨幀使用闽颇,返回"function",在IE8和更早版本的IE中寄锐,使用typeof檢測(cè)DOM節(jié)點(diǎn)中的函數(shù)(如getElementById())都返回“Objeac”而不是“function”

8兵多、檢測(cè)屬性

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

// 不好的寫法
if(object[propertyName]){ // 存在屬性propertyName
} // 不好的寫法
if(object[propertyName]!= null){ // 存在屬性propertyName
} // 不好的寫法
if(object[propertyName]橄仆!= undefined){ // 存在屬性propertyName
}

上面這段代碼中剩膘,假如屬性值為假值(false、0盆顾、null怠褐、undefined)時(shí)會(huì)出錯(cuò),判斷屬性是否存在的最好方法是使用in運(yùn)算符您宪,in運(yùn)算符僅僅會(huì)簡(jiǎn)單地判斷屬性是否存在奈懒,而不會(huì)去讀取屬性的值。

var object = {
    count: 0 } // 好的寫法
if( "count" in object ){ // 這里的代碼會(huì)執(zhí)行
} // 不好的寫法
if( object["count"] ){ // 這里的代碼不會(huì)執(zhí)行
}

9宪巨、將配置數(shù)據(jù)從代碼中分離出來

什么是配置數(shù)據(jù)磷杏?比如頁面中做某個(gè)操作失敗,需要一個(gè)提示語捏卓,而不同的操作有不同的提示語极祸,此時(shí)整個(gè)提示語就是配置數(shù)據(jù)。應(yīng)該將配置數(shù)據(jù)分離出來以參數(shù)的形式傳進(jìn)去。

10遥金、拋出自定義錯(cuò)誤 throw new Error("錯(cuò)誤提示")

在代碼執(zhí)行過程中出錯(cuò)時(shí)浴捆,如果沒有任何提示或是提示比較稀少、隱晦稿械,調(diào)試是非常困難的选泻,而拋出自定義錯(cuò)誤,就是在有可能出錯(cuò)的地方溜哮,加上捕獲錯(cuò)誤的代碼拋出錯(cuò)誤滔金,將非常有利于調(diào)試色解。拋出自己的錯(cuò)誤可以使用確切的文本供瀏覽器顯示茂嗓,可以包括出錯(cuò)的行數(shù)、函數(shù)以及失敗原因科阎,有利于快速定位錯(cuò)誤原因述吸。

ECMA-262規(guī)范指出了7種錯(cuò)誤類型

1)Error : 所有錯(cuò)誤的基本類型

2)EvalError : 通過eval()函數(shù)執(zhí)行代碼出錯(cuò)時(shí)拋出

3)RangeError : 一個(gè)數(shù)字超出了它的邊界時(shí)拋出,比如試圖創(chuàng)建一個(gè)長度為-20的數(shù)組(new Array(-20))锣笨。

4)ReferenceError: 期望的對(duì)象不存在時(shí)拋出蝌矛,比如試圖在一個(gè)null對(duì)象引用上調(diào)用一個(gè)函數(shù)

5)SyntaxError: 語法錯(cuò)誤

6)TypeError: 變量不是期望的類型時(shí)拋出錯(cuò)誤

7)URIError: 給encodeURI()、encodeURIComponent()错英、decodeURI()入撒、decodeURIComponent()等函數(shù)傳遞格式非法的URI字符串時(shí)拋出

這7種錯(cuò)誤類型需要熟記。

11椭岩、不是你的對(duì)象不要?jiǎng)?/p>

開發(fā)過程中茅逮,可能會(huì)引用一些javascript類庫,你個(gè)人不是這些類庫的作者判哥,應(yīng)該遵守3條基本原則

1)不覆蓋方法

2)不新增方法

3)不刪除方法

12献雅、瀏覽器嗅探

避免瀏覽器推斷

現(xiàn)在有一種比較流行的判斷IE瀏覽器的方法是

if( document.all ){ // IE瀏覽器
}

這就屬于瀏覽器推斷,這個(gè)推斷斷定document.all只存在于IE瀏覽器塌计,而實(shí)際上Opera的一些版本也支持document.all

做特性檢測(cè)

我們知道IE9及以下的IE瀏覽器不支持placeholder屬性挺身,當(dāng)我們要給IE9及以下瀏覽器模擬placeholder效果時(shí),需要先做特性檢測(cè)锌仅,如果瀏覽器不支持placeholder屬性才用js去模擬

if( !("placeholder" in document.createElement("input")) ){ 
    // 不支持placeholder章钾,需要模擬
}

第二部分完。


本文為轉(zhuǎn)載文章热芹。
原創(chuàng)作者:王美建

wangmeijian

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末贱傀,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子剿吻,更是在濱河造成了極大的恐慌窍箍,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異椰棘,居然都是意外死亡纺棺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門邪狞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來祷蝌,“玉大人,你說我怎么就攤上這事帆卓【揠” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵剑令,是天一觀的道長糊啡。 經(jīng)常有香客問我,道長吁津,這世上最難降的妖魔是什么棚蓄? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮碍脏,結(jié)果婚禮上梭依,老公的妹妹穿的比我還像新娘。我一直安慰自己典尾,他們只是感情好役拴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著钾埂,像睡著了一般河闰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上勃教,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天淤击,我揣著相機(jī)與錄音,去河邊找鬼故源。 笑死污抬,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绳军。 我是一名探鬼主播印机,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼门驾!你這毒婦竟也來了射赛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤奶是,失蹤者是張志新(化名)和其女友劉穎楣责,沒想到半個(gè)月后竣灌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡秆麸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年初嘹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沮趣。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡屯烦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出房铭,到底是詐尸還是另有隱情驻龟,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布缸匪,位于F島的核電站翁狐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏豪嗽。R本人自食惡果不足惜谴蔑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望龟梦。 院中可真熱鬧,春花似錦窃躲、人聲如沸计贰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽躁倒。三九已至,卻和暖如春洒琢,著一層夾襖步出監(jiān)牢的瞬間秧秉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工衰抑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留象迎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓呛踊,卻偏偏與公主長得像砾淌,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谭网,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 函數(shù)和對(duì)象 1汪厨、函數(shù) 1.1 函數(shù)概述 函數(shù)對(duì)于任何一門語言來說都是核心的概念。通過函數(shù)可以封裝任意多條語句愉择,而且...
    道無虛閱讀 4,566評(píng)論 0 5
  • 第3章 基本概念 3.1 語法 3.2 關(guān)鍵字和保留字 3.3 變量 3.4 數(shù)據(jù)類型 5種簡(jiǎn)單數(shù)據(jù)類型:Unde...
    RickCole閱讀 5,128評(píng)論 0 21
  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執(zhí)行單位為行(line)劫乱,也就是一...
    悟名先生閱讀 4,149評(píng)論 0 13
  • 板山位于寧洱縣東部的勐先鄉(xiāng)织中,該鄉(xiāng)屬中切中山河谷地貌特征,為瀾滄江水系衷戈,勐先大河由北向南流經(jīng)勐先全境抠璃。該鄉(xiāng)轄11個(gè)村...
    5ebc5e57260e閱讀 867評(píng)論 0 0
  • 影片《喊山》講農(nóng)民韓沖收留了討飯的一家子,男的經(jīng)常虐待他老婆脱惰,韓沖出于好心總?cè)裰共恕:髞眄n沖的雷管不小心炸死了討飯...
    海邊的信使閱讀 675評(píng)論 0 1