最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳細(xì)聊聊閉包在js中充當(dāng)著什么角色

 更新時間:2022年01月26日 15:31:49   作者:小小俊  
在js中,閉包是一個很重要又相當(dāng)不容易完全理解的要點,下面這篇文章主要給大家介紹了關(guān)于閉包在js中充當(dāng)著什么角色的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下

什么是閉包

開篇明義,概念先行。閉包是什么,為什么說在js中處處充滿了閉包。

閉包就是函數(shù)有權(quán)訪問另一個函數(shù)作用域中的變量,此函數(shù)和被引用的變量一起構(gòu)成了閉包

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

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

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

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

如何觀察閉包

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

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

test()()

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

閉包的錯誤認(rèn)識

說完了閉包的概念,再來說說可能大家會對閉包產(chǎn)生的一些錯誤認(rèn)識。

1.閉包的產(chǎn)生需要使用 return 暴露出去

首先從閉包的概念上來看就沒有說到閉包需要暴露到函數(shù)外才叫閉包,而是只要引用了不屬于當(dāng)前函數(shù)作用域中的變量就已經(jīng)產(chǎn)生閉包了。

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

2.閉包會導(dǎo)致內(nèi)存泄漏

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

(另外在 IE9 之后也對瀏覽器的垃圾回收機(jī)制做了優(yōu)化,現(xiàn)在已經(jīng)不容易導(dǎo)致內(nèi)存泄露了)

閉包導(dǎo)致的問題

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

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

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

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

  • 一種是使用 es6 的 let 語法生成塊級作用域,這樣每個塊級作用域中的 i 變量就不是指向同一個 i 變量,不會對彼此產(chǎn)生影響
for (let i = 0; i < 4; i++) {
    setTimeout(() => {
        console.log(i)
    }, 1000)
}  // 0, 1, 2, 3
  • 一種是使用立即執(zhí)行函數(shù),每個立即執(zhí)行函數(shù)中的變量 i 都是當(dāng)前外部變量 i 的一個快照
for (let i = 0; i < 4; i++) {
    (function(i) {
        setTimeout(() => {
            console.log(i)
        }, 1000)
    })(i)
}  // 0, 1, 2, 3

閉包的使用場景

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

1. 單例模式

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

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

2. 函數(shù)柯里化

柯里化是將一個多參數(shù)的函數(shù)轉(zhuǎn)化成幾個單參數(shù)的函數(shù)嵌套的形式,例如: 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í)行函數(shù)配合使用完成類庫的封裝

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

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

(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ā)的人應(yīng)該非常熟悉吧。

4. 保存私有變量

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

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

總結(jié)

到此這篇關(guān)于閉包在js中充當(dāng)著什么角色的文章就介紹到這了,更多相關(guān)js中的閉包內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 利用js實現(xiàn)禁止復(fù)制文本信息

    利用js實現(xiàn)禁止復(fù)制文本信息

    本文主要是通過javascript實現(xiàn)禁止瀏覽器中復(fù)制文本內(nèi)容的方法,十分的簡單,而且兼容IE和FF,有需要的小伙伴可以參考下
    2015-06-06
  • Object的相關(guān)方法 和 js遍歷對象的常用方法總結(jié)

    Object的相關(guān)方法 和 js遍歷對象的常用方法總結(jié)

    這篇文章主要介紹了Object的相關(guān)方法 和 js遍歷對象的常用方法,結(jié)合實例形式總結(jié)分析了Object對象操作的操作方法與js遍歷的三種常用方法,需要的朋友可以參考下
    2023-05-05
  • 淺析js實現(xiàn)網(wǎng)頁截圖的兩種方式

    淺析js實現(xiàn)網(wǎng)頁截圖的兩種方式

    這篇文章主要介紹了淺析js實現(xiàn)網(wǎng)頁截圖的兩種方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • 原生JS京東輪播圖代碼

    原生JS京東輪播圖代碼

    這篇文章主要為大家詳細(xì)介紹了原生JS京東輪播圖代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • JavaScript 給漢字排序?qū)嵗a

    JavaScript 給漢字排序?qū)嵗a

    數(shù)組的 sort 方法默認(rèn)字符的編碼排序,有時候要給一組漢字排序,默認(rèn)的方法就不適用了。
    2008-06-06
  • GoJs中使用HTML方法示例

    GoJs中使用HTML方法示例

    這篇文章主要為大家介紹了GoJs中使用HTML方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • JavaScript實現(xiàn)QQ聊天消息展示和評論提交功能

    JavaScript實現(xiàn)QQ聊天消息展示和評論提交功能

    這篇文章主要為大家詳細(xì)介紹了JavaScript實現(xiàn)QQ聊天消息展示和評論提交功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • js控制li的隱藏和顯示實例代碼

    js控制li的隱藏和顯示實例代碼

    下面小編就為大家?guī)硪黄猨s控制li的隱藏和顯示實例代碼。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10
  • 淺談如何使用 webpack 優(yōu)化資源

    淺談如何使用 webpack 優(yōu)化資源

    本篇文章主要介紹了淺談如何使用 webpack 優(yōu)化資源,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • javascript for循環(huán)性能測試示例

    javascript for循環(huán)性能測試示例

    這篇文章主要介紹了javascript for循環(huán)性能測試,結(jié)合實例形式分析了javascript使用for循環(huán)遍歷數(shù)組的三種常用方法及對應(yīng)的時間消耗,總結(jié)javascript使用for循環(huán)遍歷數(shù)組的相關(guān)操作技巧,需要的朋友可以參考下
    2019-08-08

最新評論

银川市| 邻水| 饶平县| 丹凤县| 柳江县| 通榆县| 松桃| 姜堰市| 灵武市| 南木林县| 社旗县| 万源市| 汤阴县| 古浪县| 将乐县| 红安县| 梓潼县| 电白县| 宁明县| 剑阁县| 河曲县| 中阳县| 桐城市| 密山市| 微博| 乐亭县| 元氏县| 乌苏市| 曲水县| 铜鼓县| 顺昌县| 盘山县| 隆尧县| 惠安县| 昭觉县| 安西县| 伊通| 金平| 新乡市| 元阳县| 洪洞县|