<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    憨厚生

    ----Java's Slave----
    ***Java's Host***

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      165 隨筆 :: 17 文章 :: 90 評(píng)論 :: 0 Trackbacks
    轉(zhuǎn) http://www.cnblogs.com/JustinYoung/articles/1350887.html

    不唐突的JavaScript的七條準(zhǔn)則

    經(jīng)過(guò)多年的開(kāi)發(fā)、教學(xué)和編寫(xiě)不唐突的JavaScript, 我發(fā)現(xiàn)了下面的一些準(zhǔn)則。我希望它們可以幫助你對(duì)“為什么這樣設(shè)計(jì)和執(zhí)行JavaScript比較好”有一點(diǎn)理解。這些規(guī)則曾經(jīng)幫助我更快地交付產(chǎn)品,并且產(chǎn)品的質(zhì)量更高,也更容易維護(hù)。

    1.不要做任何假設(shè)
    (JavaScript是一個(gè)不可靠的助手)

    可能不唐突的JavaScript 的最重要的一個(gè)特性就是——你要停止任何假設(shè):

    • 不要假設(shè)JavaScript是可用的,你最好認(rèn)為它很有可能是不可用的,而不是直接依賴(lài)于它。
    • 在你經(jīng)過(guò)測(cè)試確認(rèn)一些方法和屬性可以使用之前,不要假設(shè)瀏覽器支持它們。
    • 不要假設(shè)HTML代碼如你想象的那樣正確,每次都要進(jìn)行檢查,并且當(dāng)其不可用的時(shí)候就什么也不要做。
    • 讓JavaScript的功能獨(dú)立于輸入設(shè)備
    • 要記住其他的腳本可能會(huì)影響你的JavaScript的功能,所以要保證你的腳本的作用域盡可能地安全。

    在開(kāi)始設(shè)計(jì)你的腳本之前,要考慮的第一件事情就是檢查一下你要為其編寫(xiě)腳本的HTML代碼,看看有什么東西可以幫助你達(dá)到目的。

    2.找出鉤子和節(jié)點(diǎn)關(guān)系(HTML是腳本的基石)

    在 開(kāi)始編寫(xiě)腳本之前,要先看一下你要為之編寫(xiě)JavaScript的HTML。如果HTML是未經(jīng)組織的或者未知的,那么你幾乎不可能有一個(gè)好的腳本編寫(xiě)方 案——很可能就會(huì)出現(xiàn)下面的情況:要么是會(huì)用JavaScript創(chuàng)建太多標(biāo)記,要么就是應(yīng)用太依賴(lài)于JavaScript。

    在HTML中有一些東西需要考慮,那就是鉤子和節(jié)點(diǎn)關(guān)系。

    <1>.HTML 鉤子

    HTML 最初的和最重要的鉤子就是ID,而且ID可以通過(guò)最快的DOM方法——getElementById 訪(fǎng)問(wèn)到。如果在一個(gè)有效的HTML文檔中所有的ID都是獨(dú)一無(wú)二的話(huà)(在IE中關(guān)于name 和 ID 有一個(gè)bug,不過(guò)有些好的類(lèi)庫(kù)解決了這個(gè)問(wèn)題),使用ID就是安全可靠的,并且易于測(cè)試。

    其他一些鉤子就是是HTML元素和CSS 類(lèi),HTML元素可以通過(guò)getElementsByTagName方法訪(fǎng)問(wèn),而在多數(shù)瀏覽器中都還不能通過(guò)原生的DOM方法來(lái)訪(fǎng)問(wèn)CSS類(lèi)。不過(guò),有很 多外部類(lèi)庫(kù)提供了可以訪(fǎng)問(wèn)CSS類(lèi)名(類(lèi)似于 getElementsByClassName) 的方法。

    <2>.HTML 節(jié)點(diǎn)關(guān)系

    關(guān)于HTML的另外比較有意思的一點(diǎn)就是標(biāo)記之間的關(guān)系,思考下面的問(wèn)題:

    • 要怎樣才可以最容易地、通過(guò)最少的DOM遍歷來(lái)到達(dá)目標(biāo)節(jié)點(diǎn)?
    • 通過(guò)修改什么標(biāo)記,可以盡可能多地訪(fǎng)問(wèn)到需要修改的子節(jié)點(diǎn)?
    • 一個(gè)給定的元素有什么屬性或信息可以用來(lái)到達(dá)另外一個(gè)元素?

    遍歷DOM很耗資源而且速度很慢,這就是為什么要盡量使用瀏覽器中已經(jīng)在使用的技術(shù)來(lái)做這件事情。

    3.把遍歷交給專(zhuān)家來(lái)做(CSS,更快地遍歷DOM)

    有 關(guān)DOM的腳本和使用方法或?qū)傩裕╣etElementsByTagName, nextSibling, previousSibling, parentNode以及其它)來(lái)遍歷DOM似乎迷惑了很多人,這點(diǎn)很有意思。而有趣的是,我們其實(shí)早已經(jīng)通過(guò)另外一種技術(shù)—— CSS ——做了這些事情。

    CSS 是這樣一種技術(shù),它使用CSS選擇器,通過(guò)遍歷DOM來(lái)訪(fǎng)問(wèn)目標(biāo)元素并改變它們的視覺(jué)屬性。一段復(fù)雜的使用DOM的JavaScript可以用一個(gè)CSS選擇器取代:

    var n = document.getElementById('nav');
    if(n){
    var as = n.getElementsByTagName('a');
    if(as.length > 0){
    for(var i=0;as[i];i++){
    as[i].style.color = ‘#369′;
    as[i].style.textDecoration = ‘none’;
    }
    }
    }

    /* 下面的代碼與上面功能一樣 */

    #nav a{
    color:#369;
    text-decoration:none;
    }

    這是一個(gè)可以好好利用的很強(qiáng)大的技巧。你可以通過(guò)動(dòng)態(tài)為DOM中高層的元素添加class 或者更改元素ID來(lái)實(shí)現(xiàn)這一點(diǎn)。如果你使用DOM為文檔的body添加了一個(gè)CSS類(lèi),那么設(shè)計(jì)師就很可以容易地定義文檔的靜態(tài)版本和動(dòng)態(tài)版本。

    JavaScript:

    var dynamicClass = 'js';
    var b = document.body;
    b.className = b.className ? b.className + ' js' : 'js';

    CSS:

    /* 靜態(tài)版本 */

    #nav {
    ....
    }

    /* 動(dòng)態(tài)版本 */

    body.js #nav {
    ....
    }

    4.理解瀏覽器和用戶(hù)(在既有的使用模式上創(chuàng)建你所需要的東西)

    不 唐突的JavaScript 中很重要的一部分就是理解瀏覽器是如何工作的(尤其是瀏覽器是如何崩潰的)以及用戶(hù)期望的是什么。不考慮瀏覽器你也可以很容易地使用JavaScript 創(chuàng)建一個(gè)完全不同的界面。拖拽界面,折疊區(qū)域,滾動(dòng)條和滑動(dòng)塊都可以使用JavaScript創(chuàng)建,但是這個(gè)問(wèn)題并不是個(gè)簡(jiǎn)單的技術(shù)問(wèn)題,你需要思考下面 的問(wèn)題:

    • 這個(gè)新界面可以獨(dú)立于輸入設(shè)備么?如果不能,那么可以依賴(lài)哪些東西?
    • 我創(chuàng)建的這個(gè)新界面是否遵循了瀏覽器或者其它富界面的準(zhǔn)則(你可以通過(guò)鼠標(biāo)在多級(jí)菜單中直接切換嗎?還是需要使用tab鍵?)
    • 我需要提供什么功能但是這個(gè)功能是依賴(lài)于JavaScript的?

    最 后一個(gè)問(wèn)題其實(shí)不是問(wèn)題,因?yàn)槿绻枰憔涂梢允褂肈OM來(lái)憑空創(chuàng)建HTML。關(guān)于這點(diǎn)的一個(gè)例子就是“打印”鏈接,由于瀏覽器沒(méi)有提供一個(gè)非 JavaScript的打印文檔功能,所以你需要使用DOM來(lái)創(chuàng)建這類(lèi)鏈接。同樣地,一個(gè)實(shí)現(xiàn)了展開(kāi)和收縮內(nèi)容模塊的、可以點(diǎn)擊的標(biāo)題欄也屬于這種情況。 標(biāo)題欄不能被鍵盤(pán)激活,但是鏈接可以。所以為了創(chuàng)建一個(gè)可以點(diǎn)擊的標(biāo)題欄你需要使用JavaScript將鏈接加入進(jìn)去,然后所有使用鍵盤(pán)的用戶(hù)就可以收 縮和展開(kāi)內(nèi)容模塊了。

    解決這類(lèi)問(wèn)題的極好的資源就是設(shè)計(jì)模式庫(kù)。至于要知道瀏覽器中的哪些東西是獨(dú)立于輸入設(shè)備的,那就要靠經(jīng)驗(yàn)的積累了。首先你要理解的就是事件處理機(jī)制。

    5.理解事件(事件處理會(huì)引起改變)

    事 件處理是走向不唐突的JavaScript的第二步。重點(diǎn)不是讓所有的東西都變得可以拖拽、可以點(diǎn)擊或者為它們添加內(nèi)聯(lián)處理,而是理解事件處理是一個(gè)可以 完全分離出來(lái)的東西。我們已經(jīng)將HTML,CSS和JavaScript分離開(kāi)來(lái),但是在事件處理的分離方面卻沒(méi)有走得很遠(yuǎn)。

    事件處理器會(huì)監(jiān)聽(tīng)發(fā)生在文檔中元素上的變化,如果有事件發(fā)生,處理器就會(huì)找到一個(gè)很奇妙的對(duì)象(一般會(huì)是一個(gè)名為e的參數(shù)),這個(gè)對(duì)象會(huì)告訴元素發(fā)生了什么以及可以用它做什么。

    對(duì) 于大多數(shù)事件處理來(lái)說(shuō),真正有趣的是它不止發(fā)生在你想要訪(fǎng)問(wèn)的元素上,還會(huì)在DOM中較高層級(jí)的所有元素上發(fā)生(但是并不是所有的事件都是這 樣,focus和blur事件是例外)。舉例來(lái)說(shuō),利用這個(gè)特性你可以為一個(gè)導(dǎo)航列表只添加一個(gè)事件處理器,并且使用事件處理器的方法來(lái)獲取真正觸發(fā)事件 的元素。這種技術(shù)叫做事件委托,它有幾點(diǎn)好處:

    • 你只需要檢查一個(gè)元素是否存在,而不需要檢查每個(gè)元素
    • 你可以動(dòng)態(tài)地添加或者刪除子節(jié)點(diǎn)而并不需要?jiǎng)h除相應(yīng)的事件處理器
    • 你可以在不同的元素上對(duì)相同的事件做出響應(yīng)

    需 要記住的另一件事是,在事件向父元素傳播的時(shí)候你可以停止它而且你可以覆寫(xiě)掉HTML元素(比如鏈接)的缺省行為。不過(guò),有時(shí)候這并不是個(gè)好主意,因?yàn)闉g 覽器賦予HTML元素那些行為是有原因的。舉個(gè)例子,鏈接可能會(huì)指向頁(yè)面內(nèi)的某個(gè)目標(biāo),不去修改它們能確保用戶(hù)可以將頁(yè)面當(dāng)前的腳本狀態(tài)也加入書(shū)簽。

    6.為他人著想(命名空間,作用域和模式)

    你的代碼幾乎從來(lái)不會(huì)是文檔中的唯一的腳本代碼。所以保證你的代碼里沒(méi)有其它腳本可以覆蓋的全局函數(shù)或者全局變量就顯得尤為重要。有一些可用的模式可以來(lái)避免這個(gè)問(wèn)題,最基礎(chǔ)的一點(diǎn)就是要使用 var 關(guān)鍵字來(lái)初始化所有的變量。假設(shè)我們編寫(xiě)了下面的腳本:

    var nav = document.getElementById('nav');
    function init(){
    // do stuff
    }
    function show(){
    // do stuff
    }
    function reset(){
    // do stuff
    }

    上面的代碼中包含了一個(gè)叫做nav的全局變量和名字分別為 init,show 和 reset 的三個(gè)函數(shù)。這些函數(shù)都可以訪(fǎng)問(wèn)到nav這個(gè)變量并且可以通過(guò)函數(shù)名互相訪(fǎng)問(wèn):

    var nav = document.getElementById('nav');
    function init(){
    show();
    if(nav.className === 'show'){
    reset();
    }
    // do stuff
    }
    function show(){
    var c = nav.className;
    // do stuff
    }
    function reset(){
    // do stuff
    }

    你可以將代碼封裝到一個(gè)對(duì)象中來(lái)避免上面的那種全局式編碼,這樣就可以將函數(shù)變成對(duì)象中的方法,將全局變量變成對(duì)象中的屬性。 你需要使用“名字+冒號(hào)”的方式來(lái)定義方法和屬性,并且需要在每個(gè)屬性或方法后面加上逗號(hào)作為分割符。

    var myScript = {
    nav:document.getElementById('nav'),
    init:function(){
    // do stuff
    },
    show:function(){
    // do stuff
    },
    reset:function(){
    // do stuff
    }
    }

    所有的方法和屬性都可以通過(guò)使用“類(lèi)名+點(diǎn)操作符”的方式從外部和內(nèi)部訪(fǎng)問(wèn)到。

    var myScript = {
    nav:document.getElementById('nav'),
    init:function(){
    myScript.show();
    if(myScript.nav.className === 'show'){
    myScript.reset();
    }
    // do stuff
    },
    show:function(){
    var c = myScript.nav.className;
    // do stuff
    },
    reset:function(){
    // do stuff
    }
    }

    這種模式的缺點(diǎn)就是,你每次從一個(gè)方法中訪(fǎng)問(wèn)其它方法或?qū)傩远急仨氃谇懊婕由蠈?duì)象的名字,而且對(duì)象中的所有東西都是可以從外部訪(fǎng)問(wèn)的。如果你只是想要部分代碼可以被文檔中的其他腳本訪(fǎng)問(wèn),可以考慮下面的模塊(module)模式:

    var myScript = function(){
    //這些都是私有方法和屬性
    var nav = document.getElementById('nav');
    function init(){
    // do stuff
    }
    function show(){
    // do stuff
    }
    function reset(){
    // do stuff
    }
    //公有的方法和屬性被使用對(duì)象語(yǔ)法包裝在return 語(yǔ)句里面
    return {
    public:function(){

    },
    foo:'bar'
    }
    }();

    你 可以使用和前面的代碼同樣的方式訪(fǎng)問(wèn)返回的公有的屬性和方法,在本示例中可以這么訪(fǎng)問(wèn):myScript.public() 和 myScript.foo 。但是這里還有一點(diǎn)讓人覺(jué)得不舒服:當(dāng)你想要從外部或者從內(nèi)部的一個(gè)私有方法中訪(fǎng)問(wèn)公有方法的時(shí)候,還是要寫(xiě)一個(gè)冗長(zhǎng)的名字(對(duì)象的名字可以非常長(zhǎng))。為 了避免這一點(diǎn),你需要將它們定義為私有的并且在return語(yǔ)句中只返回一個(gè)別名:

    var myScript = function(){
    // 這些都是私有方法和屬性
    var nav = document.getElementById('nav');
    function init(){
    // do stuff
    }
    function show(){
    // do stuff
    // do stuff
    }
    function reset(){
    // do stuff
    }
    var foo = 'bar';
    function public(){

    }

    //只返回指向那些你想要訪(fǎng)問(wèn)的私有方法和屬性的指針
    return {
    public:public,
    foo:foo
    }
    }();

    這就保證了代碼風(fēng)格一致性,并且你可以使用短一點(diǎn)的別名來(lái)訪(fǎng)問(wèn)其中的方法或?qū)傩浴?/p>

    如果你不想對(duì)外部暴露任何的方法或?qū)傩?,你可以將所有的代碼封裝到一個(gè)匿名方法中,并在它的定義結(jié)束后立刻執(zhí)行它:

    (function(){
    // these are all private methods and properties
    var nav = document.getElementById('nav');
    function init(){
    // do stuff
    show(); // 這里不需要類(lèi)名前綴
    }
    function show(){
    // do stuff
    }
    function reset(){
    // do stuff
    }
    })();

    對(duì)于那些只執(zhí)行一次并且對(duì)其它函數(shù)沒(méi)有依賴(lài)的代碼模塊來(lái)說(shuō),這種模式非常好。

    通過(guò)遵循上面的那些規(guī)則,你的代碼更好地為用戶(hù)工作,也可以使你的代碼在機(jī)器上更好地運(yùn)行并與其他開(kāi)發(fā)者的代碼和睦相處。不過(guò),還有一個(gè)群體需要考慮到。

    7.為接手的開(kāi)發(fā)者考慮(使維護(hù)更加容易)

    使你的腳本真正地unobtrusive的最后一步是在編寫(xiě)完代碼之后仔細(xì)檢查一遍,并且要照顧到一旦腳本上線(xiàn)之后要接手你的代碼的開(kāi)發(fā)者??紤]下面的問(wèn)題:

    • 所有的變量和函數(shù)名字是否合理并且易于理解?
    • 代碼是否經(jīng)過(guò)了合理的組織?從頭到尾都很流暢嗎?
    • 所有的依賴(lài)都顯而易見(jiàn)嗎?
    • 在那些可能引起混淆的地方都添加了注釋嗎?

    最重要的一點(diǎn)是:要認(rèn)識(shí)到文檔中的HTML和CSS代碼相對(duì)于JavaScript來(lái)說(shuō)更有可能被改變(因?yàn)樗鼈冐?fù)責(zé)視覺(jué)效果)。所以不要在腳本代碼中包含任何可以讓終端用戶(hù)看到的class和ID,而是要將它們分離出來(lái)放到一個(gè)保存配置信息的對(duì)象中。

    myscript = function(){
    var config = {
    navigationID:'nav',
    visibleClass:'show'
    };
    var nav = document.getElementById(config.navigationID);
    function init(){
    show();
    if(nav.className === config.visibleClass){
    reset();
    };
    // do stuff
    };
    function show(){
    var c = nav.className;
    // do stuff
    };
    function reset(){
    // do stuff
    };
    }();

    這樣維護(hù)者就知道去哪里修改這些屬性,而不需要改動(dòng)其他代碼。

    更多信息

    以上就是我發(fā)現(xiàn)的七條準(zhǔn)則。如果你想要了解更多與上面所探討的主題相關(guān)的東西,可以看看下面的鏈接:



    posted on 2009-03-19 16:13 二胡 閱讀(149) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): JS 、web系統(tǒng)開(kāi)發(fā)
    主站蜘蛛池模板: 亚洲AV无码乱码在线观看代蜜桃| 久9久9精品免费观看| 亚洲成人一级电影| 亚洲日韩在线观看免费视频| 成人免费AA片在线观看| 成人爽a毛片免费| 黄网站在线播放视频免费观看| 亚洲欧洲综合在线| 亚洲AV无码一区东京热| 亚洲M码 欧洲S码SSS222| 成年女人男人免费视频播放 | 国产无人区码卡二卡三卡免费 | 亚洲av无码不卡私人影院| 亚洲成在人线aⅴ免费毛片| 免费成人在线电影| 国产精品免费久久久久久久久| 国产午夜亚洲精品不卡| 亚洲国产精品无码久久九九大片| 亚洲毛片在线免费观看| 亚洲视频免费在线看| 亚洲精品免费视频| 久久精品国产亚洲av麻| 亚洲韩国精品无码一区二区三区 | 免费看又黄又爽又猛的视频软件| 亚洲中文字幕久久久一区| 亚洲国产高清美女在线观看 | 无码区日韩特区永久免费系列 | 男女啪啪永久免费观看网站| 成人免费视频77777| 性做久久久久久久免费看| 四虎成年永久免费网站 | 亚洲另类激情综合偷自拍图| 午夜亚洲国产成人不卡在线| 全免费a级毛片免费看无码| 成全视频在线观看免费高清动漫视频下载| 99久久精品免费精品国产| 99在线观看视频免费| 1000部免费啪啪十八未年禁止观看| 91青青国产在线观看免费| 91精品成人免费国产片| 精品国产无限资源免费观看|