Javascript語言精粹(二)

來源:互聯網
上載者:User

標籤:

閉包
// 建立一個建構函式quo// 它帶有get_status方法和status私人屬性var quo = function(status){    return {        get_status: function(){            return status;        }    };};var myQuo = quo(‘amazing‘);alert(myQuo.get_status());

當我們調用quo時,它返回一個對象:

①該對象包含一個get_status方法,②該對象的一個引用儲存在myQuo中。

即使quo已經返回了(return status;),但get_status方法仍然有訪問status屬性的特權。

get_status方法訪問的並不是status參數的副本,而是status參數本身!

因為該函數可以訪問它被建立時所處的上下文環境。也因此該函數被稱為閉包。

 

再看一個更有用的栗子:

// 定義一個函數,它使一個DOM節點的背景色由黃變白var fade = function(node){    var level = 1;    var step = function(){        var hex = level.toString(16);        node.style.backgroundColor = ‘#FFFF‘ + hex + hex;        if(hex < 15){            level += 1;            setTimeout(step, 100);        }    };    setTimeout(step, 100);};fade(document.body);

只要fade的內建函式step需要levellevel變數就會持續保留。

 

糟糕的栗子:

// 彈出節點的序號var add_the_handlers = function(nodes){    var i;    for(i=0; i<nodes.length; i++){        nodes[i].onclick = function(){            alert(i);  //總是彈出節點的數目        };    }};

未能達到目的的原因,是因為onclick時間處理器函數綁定了變數 i 本身,而不是函數在構造時的變數 i 的值

(個人理解:js解析的時候,把for迴圈解析了一遍, 啟動並執行時候 i 已經等於節點數目了。綁定了 i 本身,故彈出的 i 等於節點數目。我們需要彈出的 i 是在它被構造時的值。)

 

解決糟糕的栗子:

var add_the_handlers = function(nodes){    var helper = function(i){        return function(){            alert(i);        };    };    var i;    for(i=0; i<nodes.length; i++){        nodes[i].onclick = helper(i);    }};

避免在迴圈中建立函數,這會帶來無謂的計算,還會引起混淆。

可以在迴圈之外先建立一個輔助函數helper,讓輔助函數返回一個綁定了當前 i 值的函數,這樣就不會混淆了。

 

模組

我們可以使用函數和閉包來構建模組,這幾乎可以完全摒棄全域變數的使用。

模組是一個提供介面卻隱藏狀態和實現的函數或對象。

模組模式也可以用來產生安全的對象。

我們來構造一個產生序號的對象:

var serial_maker = function(){// 該對象包含一個設定首碼的方法// 該對象包含一個設定序號的方法// 和一個產生字串的方法        var prefix = ‘‘; //首碼    var seq = 0; //序號    return {        set_prefix: function(p){            prefix = String(p);        },        set_seq: function(s){            seq = s;        },        generate: function(){            var result = prefix + seq;            seq += 1;            return result;        }    };};// 調用var seqer = serial_maker();seqer.set_prefix(‘Q‘);seqer.set_seq(1000);var unique = seqer.generate(); // "Q1000"

如果我們把seqer.generate作為一個值傳遞給第三方函數,這個函數能產生唯一的字串,但卻不能通過它來改變prefix和seq的值。

 

Javascript語言精粹(二)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.