• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
    問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
    當前位置: 首頁 - 科技 - 知識百科 - 正文

    通俗易懂地解釋JS中的閉包

    來源:懂視網 責編:小采 時間:2020-11-27 22:27:21
    文檔

    通俗易懂地解釋JS中的閉包

    通俗易懂地解釋JS中的閉包:1. 閉包就是跨作用域訪問變量。 【示例一】 var name = 'wangxi' function user () { // var name = 'wangxi' function getName () { console.log(name) } getName() } user() // wangxi 在 getName 函
    推薦度:
    導讀通俗易懂地解釋JS中的閉包:1. 閉包就是跨作用域訪問變量。 【示例一】 var name = 'wangxi' function user () { // var name = 'wangxi' function getName () { console.log(name) } getName() } user() // wangxi 在 getName 函

    1. "閉包就是跨作用域訪問變量。"

    【示例一】

    var name = 'wangxi'
    function user () {
     // var name = 'wangxi'
     function getName () {
     console.log(name)
     }
     getName()
    }
    user() // wangxi

    在 getName 函數中獲取 name,首先在 getName 函數的作用域中查找 name,未找到,進而在 user 函數的作用域中查找,同樣未找到,繼續向上回溯,發現在全局作用域中存在 name,因此獲取 name 值并打印。這里很好理解,即變量都存在在指定的作用域中,如果在當前作用中找不到想要的變量,則通過作用域鏈向在父作用域中繼續查找,直到找到第一個同名的變量為止(或找不到,拋出 ReferenceError 錯誤)。這是 js 中作用域鏈的概念,即子作用域可以根據作用域鏈訪問父作用域中的變量,那如果相反呢,在父作用域想訪問子作用域中的變量呢?——這就需要通過閉包來實現。

    【示例二】

    function user () {
     var name = 'wangxi'
     return function getName () {
     return name
     }
    }
    var userName = user()()
    console.log(userName) // wangxi

    分析代碼我們知道,name 是存在于 user 函數作用域內的局部變量,正常情況下,在外部作用域(這里是全局)中是無法訪問到 name 變量的,但是通過閉包(返回一個包含變量的函數,這里是 getName 函數),可以實現跨作用域訪問變量了(外部訪問內部)。因此上面的這種說法完整的應該理解為:

    閉包就是跨作用域訪問變量 —— 內部作用域可以保持對外部作用域中變量的引用從而使得(更)外部作用域可以訪問內部作用域中的變量。(還是不理解的話看下一條分析)

    2. "閉包:在爺爺的環境中執行了爸爸,爸爸中返回了孫子,本來爸爸被執行完了,爸爸的環境應該被清除掉,但是孫子引用了爸爸的環境,導致爸爸釋放不了。這一坨就是閉包。簡單來講,閉包就是一個引用了父環境的對象,并且從父環境中返回到更高層的環境中的一個對象。"

    這個怎么理解呢?首先看下方代碼:

    【示例三】

    function user () {
     var name = 'wangxi'
     return name
    }
    var userName = user()
    console.log(userName) // wangxi

    問:這是閉包嗎?

    答:當然不是。首先要明白閉包是什么。雖然這里形式上看好像也是在全局作用域下訪問了 user 函數內的局部變量 name,但是問題是,user 執行完,name 也隨之被銷毀了,即函數內的局部變量的生命周期僅存在于函數的聲明周期內,函數被銷毀,函數內的變量也自動被銷毀。

    但是使用閉包就相反,函數執行完,生命周期結束,但是通過閉包引用的外層作用域內的變量依然存在,并且將一直存在,直到執行閉包的的作用域被銷毀,這里的局部變量才會被銷毀(如果在全局環境下引用了閉包,則只有在全局環境被銷毀,比如程序結束、瀏覽器關閉等行為時才會銷毀閉包引用的作用域)。因此為了避免閉包造成的內存損耗,建議在使用閉包后手動銷毀。還是上面示例二的例子,稍作修改:

    【示例四】

    function user () {
     var name = 'wangxi'
     return function getName () {
     return name
     }
    }
    var userName = user()() // userName 變量中始終保持著對 name 的引用
    console.log(userName) // wangxi
    userName = null // 銷毀閉包,釋放內存

    【為什么 user()() 是兩個括號:執行 user()  返回的是 getName 函數,要想獲得 name 變量,需要對返回的 getName 函數執行一次,所以是 user()()】

    根據觀點2,分析一下代碼:在全局作用域下創建了 userName 變量(爺爺),保存了對 user 函數最終返回結果的引用(即局部變量 name 的值),執行 user()()(爸爸),返回了 name(孫子),正常情況下,在執行了 user()() 之后,user 的環境(爸爸)應該被清除掉,但是因為返回的結果 name(孫子)引用了爸爸的環境(因為 name 本來就是存在于 user 的作用域內的),導致 user 的環境無法被釋放(會造成內存損耗)。

    那么【"閉包就是一個引用了父環境的對象,并且從父環境中返回到更高層的環境中的一個對象。"】如何理解?

    我們換個說法:如果一個函數引用了父環境中的對象,并且在這個函數中把這個對象返回到了更高層的環境中,那么,這個函數就是閉包。

    還是看上面的例子:

    getName 函數中引用了 user(父)環境中的對象(變量 name),并且在函數中把 name 變量返回到了全局環境(更高層的環境)中,因此,getName 就是閉包。

    3. "JavaScript中的函數運行在它們被定義的作用域里,而不是它們被執行的作用域里."

    這句話對閉包中對變量的引用的理解很有幫助。我們看下面的例子:

    var name = 'Schopenhauer'
    function getName () {
     console.log(name)
    }
    function myName () {
     var name = 'wangxi'
     getName()
    }
    myName() // Schopenhauer

    如果執行 myName() 輸出的結果和你想象的不一樣,你就要再回去看看上面說的這句話了,

    JavaScript 中的函數運行在它們被定義的作用域里,而不是它們被執行的作用域里

    執行 myName,函數內部執行了 getName,而 getName 是在全局環境下定義的,因此盡管在 myName 中定義了變量 name,對getName 的執行并無影響,getName 中打印的依然是全局作用域下的 name。

    我們稍微改一下代碼:

    var name = 'Schopenhauer'
    function getName () {
      var name = 'Aristotle'
     var intro = function() { // 這是一個閉包
     console.log('I am ' + name)
     }
     return intro
    }
    function showMyName () {
     var name = 'wangxi'
     var myName = getName()
     myName()
    }
    showMyName() // I am Aristotle

    結果和你想象的一樣嗎?結果留作聰明的你自己分析~

    聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    通俗易懂地解釋JS中的閉包

    通俗易懂地解釋JS中的閉包:1. 閉包就是跨作用域訪問變量。 【示例一】 var name = 'wangxi' function user () { // var name = 'wangxi' function getName () { console.log(name) } getName() } user() // wangxi 在 getName 函
    推薦度:
    標簽: 里面的 解釋 閉包
    • 熱門焦點

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 久久国产精品一国产精品金尊| 久久精品国产久精国产思思 | 日韩精品无码一区二区三区不卡| 久久精品国产亚洲沈樵| 在线涩涩免费观看国产精品| 国产精品无码免费专区午夜| 99国产精品永久免费视频| 亚洲欧洲精品成人久久奇米网| 国产线视频精品免费观看视频| 成人精品视频一区二区三区 | 欧美精品中文字幕亚洲专区| 亚洲爆乳精品无码一区二区| 国产精品丝袜久久久久久不卡| 97久久精品午夜一区二区| 久久精品国产亚洲AV香蕉| 国产成人精品无码免费看| 51国偷自产精品一区在线视频| 日韩av无码久久精品免费| 久久精品国产一区二区电影| 亚洲精品成人av在线| 国产成人精品视频播放| 久久亚洲日韩精品一区二区三区| 香蕉99久久国产综合精品宅男自| 国内精品久久久久久久久电影网| 四虎精品影院永久在线播放| 99国产精品久久久久久久成人热| 精品欧洲AV无码一区二区男男| 亚洲国产精品无码久久久秋霞2 | 国产亚洲精品激情都市| 99视频在线精品国自产拍亚瑟| 国产精品毛片久久久久久久| 2022年国产精品久久久久| 久久99国产精品尤物| 久久精品人人做人人爽97| 漂亮人妻被黑人久久精品| 人妻少妇精品无码专区二区| 亚洲欧美精品SUV| 无码日韩精品一区二区免费暖暖| 亚洲AV永久青草无码精品| 爽爽精品dvd蜜桃成熟时电影院| 欧洲精品久久久av无码电影|