1. 程式人生 > 程式設計 >Javascript閉包使用場景原理詳細

Javascript閉包使用場景原理詳細

目錄
  • 一、閉包
  • 二、閉包的使用場景
    • 1.setTimwww.cppcns.comeout
    • 2.回撥
    • 3.函式防抖
    • 4.封裝私有變數

Javascript閉包使用場景原理詳細

一、閉包

中,只有函式內部的子函式才能讀取區域性變數,閉包就是能夠讀取其他函式內部變數的函式。

比如下面的程式碼:

function f1() {
    var n = 999;
    function f2() {
    console.log(n);
    }
    return f2;
}
var result = f1();
result();//999

  函式f2就被包括在函式f1內部,這時f1內部的所有區域性變數,對f2都是可見的。但是反過來就不行,f2內部的區域性變數,對f1就是不可見的。

  這就是script語言特有的"鏈式作用域"結構(chain scope),子物件會一級一級地向上尋找所有父物件的變數。所以,父物件的所有變數,對子物件都是可見的,反之則不成立。

  既然f2可以讀取f1中的區域性變數,那麼只要把f2作為返回值,就可以在f1外部讀取它的內部變量了。

二、閉包的使用場景

1.setTimeout

  原生的setTimeout傳遞的第一個函式不能帶引數,通過閉包可以實現傳參效果。

function f1(a) {
    function f2() {
      www.cppcns.com  console.log(a);
    }
    return f2;
}
var fun = f1(1);
setTimeout(fun,10www.cppcns.com
00);//一秒之後打印出1

2.回撥

  定義行為,然後把它關聯到某個使用者事件上(點選或者按鍵)。程式碼通常會作為一個回撥(事件觸發時呼叫的函式)繫結到事件。

  比如下面這段程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>測試</title>
</head>
<body>
    <a href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  id="size-12">12</a>
    <a href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  id="size-20">20</a>
    <a href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  id="size-30">30</a>

    <script type="text/javascript">
        function changeSize(size){
            return function(){
                document.body.style.fontSize = size + 'px';
   
}; } vahttp://www.cppcns.comr size12 = changeSize(12); var size14 = changeSize(20); var size16 = changeSize(30); document.getElementById('size-12').onclick = size12; document.getElementById('size-20').onclick = size14; document.getElementById('size-30').onclick = size16; </script> </body> </html>

當點選數字時,字型也會變成相應的大小。

3.函式防抖

  在事件被觸發n秒後再執行回撥,如果在這n秒內又被觸發,則重新計時。

   實現的關鍵就在於setTimeOut這個函式,由於還需要一個變數來儲存計時,考慮維護全域性純淨,可以藉助閉包來實現。

   如下程式碼所示:

/*
* fn [function] 需要防抖的函式
* delay [number] 毫秒,防抖期限值
*/
function debounce(fn,delay){
    let timer = null
    //藉助閉包
    return function() {
        if(timer){
            clearTimeout(timer) //進入該分支語句,說明當前正在一個計時過程中,並且又觸發了相同事件。所以要取消當前的計時,重新開始計時
            timer = setTimeOut(fn,delay) 
        }else{
            timer = setTimeOut(fn,delay) // 進入該分支說明當前並沒有在計時,那麼就開始一個計時
        }
    }
}

4.封裝私有變數

  如下面程式碼:用建立一個計數器

  方法1:

function f1() {
    var sum = 0;
    var obj = {
       inc:function () {
           sum++;
           return sum;
       }
};
    return obj;
}
let result = f1();
console.log(result.inc());//1
console.log(result.inc());//2
console.log(result.inc());//3

  在返回的物件中,實現了一個閉包,該閉包攜帶了區域性變數x,並且,從外部程式碼根本無法訪問到變數x。

  方法2:

function f1() {
    var sum = 0;
    function f2() {
        sum++;
        return f2;
    }
    f2.valueOf = function () {
        return sum;
    };
    f2.toString = function () {
        return sum+'';
    };
    return f2;
}
//執行函式f1,返回的是函式f2
console.log(+f1());//0
console.log(+f1()())//1
console.log(+f1()()())//2


所有js資料型別都擁有valueOftoString這兩個方法,null除外

  • valueOf()方法:返回指定物件的原始值。
  • toString()方法:返回物件的字串表示。

在數值運算中,優先呼叫了valueOf,字串運算中,優先呼叫toString
sum+' '是一個字串型別的資料

到此這篇關於Javascript閉包的使用場景的文章就介紹到這了,更多相關Javascript閉包內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!