溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

閉包在js中是什么意思

發(fā)布時間:2022-01-27 09:16:52 來源:億速云 閱讀:129 作者:kk 欄目:開發(fā)技術

這篇文章跟大家分析一下“閉包在js中是什么意思”。內容詳細易懂,對“閉包在js中是什么意思”感興趣的朋友可以跟著小編的思路慢慢深入來閱讀一下,希望閱讀后能夠對大家有所幫助。下面跟著小編一起深入學習“閉包在js中是什么意思”的知識吧。

    什么是閉包

    閉包是什么,為什么說在js中處處充滿了閉包。

    閉包就是函數有權訪問另一個函數作用域中的變量,此函數和被引用的變量一起構成了閉包

    文字描述文縐縐的難以理解,看一下代碼就能夠一目了然了

    function test() {
        var a = 1
        var b = function() {
            console.log(a)
        }
        
        return b
    }

    在上面的代碼例子中,變量 a 處于函數 test 的作用域中,但是函數 b 中可以對變量 a 進行訪問。
    套用閉包的概念,也就是函數 b 有權訪問函數 test 作用域中的變量 a,此時函數 b 與變量 a 就形成了一個閉包。

    看了上面的例子,大家是否恍然大悟,這不就是我們在代碼中經常寫的嗎。所以說js中處處充滿了閉包。

    如何觀察閉包

    如果一開始我們對于閉包的認識還不是很深刻,我們怎么知道在代碼中寫出了一個閉包呢?一招教你找出閉包

    function test() {
        let a = 1
        return function test1() {
            debugger
            console.log(a)
        }
    }
    
    test()()

    如上的一段代碼,在執(zhí)行到 debugger 關鍵字的時候,我們可以打開瀏覽器的開發(fā)者調制工具,此時我們可以從調用棧中看到 Closure 的字樣,這就是代表我們寫出了一個閉包啦

    閉包在js中是什么意思

    閉包的錯誤認識

    說完了閉包的概念,再來說說可能大家會對閉包產生的一些錯誤認識。

    1.閉包的產生需要使用 return 暴露出去

    首先從閉包的概念上來看就沒有說到閉包需要暴露到函數外才叫閉包,而是只要引用了不屬于當前函數作用域中的變量就已經產生閉包了。

    為什么會有這樣的錯誤認識,是因為我們使用閉包引用了外部作用域中的變量,一般是為了將這個變量或者是這個函數暴露出去,讓我們在外部也可以訪問到這個變量或者函數,也就是說將閉包暴露到函數外部只是我們的業(yè)務需求,而不是閉包的必要條件。

    閉包在js中是什么意思

    2.閉包會導致內存泄漏

    首先我們要知道為什么閉包會導致內存泄漏,是因為我們將閉包暴露到函數外部的時候,閉包內部仍然引用著其外部作用域中的變量,導致外部作用域中的變量無法被垃圾回收機制回收,如果循環(huán)引用閉包的話就容易造成內存泄漏的現象。但這是由于我們在使用閉包過程中所引起的,而不是閉包本身的性質所決定的,因此說閉包一定會導致內存泄漏是不嚴謹的。

    (另外在 IE9 之后也對瀏覽器的垃圾回收機制做了優(yōu)化,現在已經不容易導致內存泄露了)

    閉包在js中是什么意思

    閉包導致的問題

    作為 js 中八大陷阱之一的循環(huán)陷阱,就是由于閉包引起的

    for (var i = 0; i < 4; i++) {
        setTimeout(() => {
            console.log(i)
        }, 1000)
    }  // 4, 4, 4, 4

    執(zhí)行以上代碼,會發(fā)現 1s 之后打印了 4個 4,為什么不是打印 0, 1, 2, 3,就是因為 setTimeout 中的回調函數是一個閉包,引用了外部作用域中的 i 變量,但是 i 只有一個,并不會在每個回調中生成新的 i,因此在 1s 后打印的時候訪問的是同一個作用域中的 i 變量,因此打印的結果就是 4個 4

    如何解決以上問題,有兩個方法:

    • 一種是使用 es6 的 let 語法生成塊級作用域,這樣每個塊級作用域中的 i 變量就不是指向同一個 i 變量,不會對彼此產生影響

    for (let i = 0; i < 4; i++) {
        setTimeout(() => {
            console.log(i)
        }, 1000)
    }  // 0, 1, 2, 3
    • 一種是使用立即執(zhí)行函數,每個立即執(zhí)行函數中的變量 i 都是當前外部變量 i 的一個快照

    for (let i = 0; i < 4; i++) {
        (function(i) {
            setTimeout(() => {
                console.log(i)
            }, 1000)
        })(i)
    }  // 0, 1, 2, 3

    閉包的使用場景

    說了這么多閉包的性質,甚至閉包還會引發(fā)循環(huán)陷阱這么重大的問題,那么閉包到底有什么用?面試官問到的時候總不能說 js 處處都是閉包,所以 js 到處都是閉包的使用場景吧。那么我們就來說說閉包的幾個經典使用場景

    1. 單例模式

    var CreateSingleton = (function() {
        var instance = null
        var CreateSingleton = function() {
            if (instance) return instance
            return instance = this
        }
        return CreateSingleton
    })()

    單例模式是設計模式的一種,目的是為了保證全局中只有一個實例對象,上述代碼利用 instance 創(chuàng)建一個閉包。單例模式在組件庫保證全局中只有一個彈窗組件尤其好用。

    2. 函數柯里化

    柯里化是將一個多參數的函數轉化成幾個單參數的函數嵌套的形式,例如: function test(a, b, c) => function test(a)(b)(c)

    function currying(fn, args) {
      var _this = this
      var len = fn.length
      var args = args || []
    
      return function() {
        var _args = Array.prototype.slice.call(arguments)
        Array.prototype.push.apply(args, _args)
        
        if(_args.length < len) {
          return currying.call(this, fn, _args)
        }
    
        return fn.apply(this, _args)
      }
    }

    3. 與立即執(zhí)行函數配合使用完成類庫的封裝

    閉包往往配合著立即執(zhí)行函數來一起使用,能夠發(fā)揮出強大的效果。因此,往往很多人容易被誤導,認為閉包與立即執(zhí)行函數之間有什么關系,甚至認為立即執(zhí)行函數就是閉包。但這種認識其實是錯誤的,立即執(zhí)行函數與閉包之間沒有任何關系。

    在 jQuery 盛行的年代,各類規(guī)范百花爭艷,其中 umd 規(guī)范能夠兼容多種環(huán)境,主要在于其 umd 頭部結構的實現

    (function( global, factory ) {
        "use strict";
        if ( typeof module === "object" && typeof module.exports === "object" ) {
            module.exports = global.document ?
            factory( global, true ) :
    	function( w ) {
                if ( !w.document ) {
    		throw new Error( "jQuery requires a window with a document" );
                }
                return factory( w );
    	};
        } else {
    	factory( global );
        }
    })( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {})

    以上這種代碼的寫法使用過 jQuery 開發(fā)的人應該非常熟悉吧。

    4. 保存私有變量

    在實際開發(fā)過程中,我們有時候需要對于計算結果進行緩存,或者是保存私有變量而不被外部訪問到,就可以使用閉包來實現。

    另外,在目前流行的兩大前端框架 Vue 和 React 中其實也大量用到了閉包進行相關功能的實現,具體大家可以自己翻翻源碼啦~

    javascript是一種什么語言

    javascript是一種動態(tài)類型、弱類型的語言,基于對象和事件驅動并具有相對安全性并廣泛用于客戶端網頁開發(fā)的腳本語言,同時也是一種廣泛用于客戶端Web開發(fā)的腳本語言。它主要用來給HTML網頁添加動態(tài)功能,現在JavaScript也可被用于網絡服務器,如Node.js。

    關于閉包在js中是什么意思就分享到這里啦,希望上述內容能夠讓大家有所提升。如果想要學習更多知識,請大家多多留意小編的更新。謝謝大家關注一下億速云網站!

    向AI問一下細節(jié)

    免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI