<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答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
        主站蜘蛛池模板: 亚在线观看免费视频入口| 一级毛片免费不卡| 黄页网站在线看免费| 亚洲色图.com| 精品一区二区三区免费毛片爱| 亚洲国产成人高清在线观看| 久草视频在线免费看| 亚洲激情中文字幕| 国产91色综合久久免费分享| 91亚洲视频在线观看| 在线看片无码永久免费视频| 亚洲中文无码mv| 亚洲国产成人久久精品99| 国产精品1024在线永久免费| 国产亚洲精品自在线观看| 女人隐私秘视频黄www免费| 久久久久亚洲av无码专区喷水| 日本在线高清免费爱做网站| 亚洲日韩乱码中文字幕| 免费国产成人高清在线观看麻豆| 一级毛片试看60分钟免费播放| 相泽亚洲一区中文字幕| 免费人成视频在线观看网站| 亚洲欧洲日韩极速播放| 国产免费看插插插视频| 999zyz**站免费毛片| 亚洲精品在线不卡| 麻豆国产人免费人成免费视频 | 亚洲中文字幕无码久久| 日日夜夜精品免费视频| 成人免费网站久久久| 亚洲国产成人久久综合碰碰动漫3d| 国产精彩免费视频| 黄色免费网址在线观看| 亚洲一区二区成人| 黄色片在线免费观看 | 黄床大片30分钟免费看| 在线观看亚洲成人| 国产成在线观看免费视频| 永久免费无码网站在线观看个| 亚洲视频在线观看免费视频|