溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Javascript閉包使用場(chǎng)景的原理分析

發(fā)布時(shí)間:2021-11-11 11:06:32 來源:億速云 閱讀:163 作者:小新 欄目:開發(fā)技術(shù)

這篇文章給大家分享的是有關(guān)Javascript閉包使用場(chǎng)景的原理分析的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。

一、閉包

Javascript中,只有函數(shù)內(nèi)部的子函數(shù)才能讀取局部變量,閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。

比如下面的代碼:

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

  函數(shù)f2就被包括在函數(shù)f1內(nèi)部,這時(shí)f1內(nèi)部的所有局部變量,對(duì)f2都是可見的。但是反過來就不行,f2內(nèi)部的局部變量,對(duì)f1就是不可見的。

  這就是Javascript語言特有的"鏈?zhǔn)阶饔糜?quot;結(jié)構(gòu)(chain scope),子對(duì)象會(huì)一級(jí)一級(jí)地向上尋找所有父對(duì)象的變量。所以,父對(duì)象的所有變量,對(duì)子對(duì)象都是可見的,反之則不成立。

  既然f2可以讀取f1中的局部變量,那么只要把f2作為返回值,就可以在f1外部讀取它的內(nèi)部變量了。

二、閉包的使用場(chǎng)景

1.setTimeout

  原生的setTimeout傳遞的第一個(gè)函數(shù)不能帶參數(shù),通過閉包可以實(shí)現(xiàn)傳參效果。

function f1(a) {
    function f2() {
        console.log(a);
    }
    return f2;
}
var fun = f1(1);
setTimeout(fun,1000);//一秒之后打印出1

2.回調(diào)

  定義行為,然后把它關(guān)聯(lián)到某個(gè)用戶事件上(點(diǎn)擊或者按鍵)。代碼通常會(huì)作為一個(gè)回調(diào)(事件觸發(fā)時(shí)調(diào)用的函數(shù))綁定到事件。

  比如下面這段代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>測(cè)試</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';
            };
        }

        var 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>

當(dāng)點(diǎn)擊數(shù)字時(shí),字體也會(huì)變成相應(yīng)的大小。

3.函數(shù)防抖

   在事件被觸發(fā)n秒后再執(zhí)行回調(diào),如果在這n秒內(nèi)又被觸發(fā),則重新計(jì)時(shí)。

   實(shí)現(xiàn)的關(guān)鍵就在于setTimeOut這個(gè)函數(shù),由于還需要一個(gè)變量來保存計(jì)時(shí),考慮維護(hù)全局純凈,可以借助閉包來實(shí)現(xiàn)。

   如下代碼所示:

/*
* fn [function] 需要防抖的函數(shù)
* delay [number] 毫秒,防抖期限值
*/
function debounce(fn,delay){
    let timer = null
    //借助閉包
    return function() {
        if(timer){
            clearTimeout(timer) //進(jìn)入該分支語句,說明當(dāng)前正在一個(gè)計(jì)時(shí)過程中,并且又觸發(fā)了相同事件。所以要取消當(dāng)前的計(jì)時(shí),重新開始計(jì)時(shí)
            timer = setTimeOut(fn,delay) 
        }else{
            timer = setTimeOut(fn,delay) // 進(jìn)入該分支說明當(dāng)前并沒有在計(jì)時(shí),那么就開始一個(gè)計(jì)時(shí)
        }
    }
}

4.封裝私有變量

  如下面代碼:用js創(chuàng)建一個(gè)計(jì)數(shù)器

  方法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

  在返回的對(duì)象中,實(shí)現(xiàn)了一個(gè)閉包,該閉包攜帶了局部變量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;
}
//執(zhí)行函數(shù)f1,返回的是函數(shù)f2
console.log(+f1());//0
console.log(+f1()())//1
console.log(+f1()()())//2

所有js數(shù)據(jù)類型都擁有valueOftoString這兩個(gè)方法,null除外

  • valueOf()方法:返回指定對(duì)象的原始值。

  •  toString()方法:返回對(duì)象的字符串表示。

在數(shù)值運(yùn)算中,優(yōu)先調(diào)用了valueOf,字符串運(yùn)算中,優(yōu)先調(diào)用toString
   sum+' '是一個(gè)字符串類型的數(shù)據(jù)

感謝各位的閱讀!關(guān)于“Javascript閉包使用場(chǎng)景的原理分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI