<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
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        深入理解javascript作用域和閉包_基礎知識

        來源:懂視網(wǎng) 責編:小采 時間:2020-11-27 21:27:19
        文檔

        深入理解javascript作用域和閉包_基礎知識

        深入理解javascript作用域和閉包_基礎知識:作用域 作用域是一個變量和函數(shù)的作用范圍,javascript中函數(shù)內聲明的所有變量在函數(shù)體內始終是可見的,在javascript中有全局作用域和局部作用域,但是沒有塊級作用域,局部變量的優(yōu)先級高于全局變量,通過幾個示例來了解下javascript中作用域的那些潛
        推薦度:
        導讀深入理解javascript作用域和閉包_基礎知識:作用域 作用域是一個變量和函數(shù)的作用范圍,javascript中函數(shù)內聲明的所有變量在函數(shù)體內始終是可見的,在javascript中有全局作用域和局部作用域,但是沒有塊級作用域,局部變量的優(yōu)先級高于全局變量,通過幾個示例來了解下javascript中作用域的那些潛

        作用域

        作用域是一個變量和函數(shù)的作用范圍,javascript中函數(shù)內聲明的所有變量在函數(shù)體內始終是可見的,在javascript中有全局作用域和局部作用域,但是沒有塊級作用域,局部變量的優(yōu)先級高于全局變量,通過幾個示例來了解下javascript中作用域的那些“潛規(guī)則”(這些也是在前端面試中經(jīng)常問到的問題)。

        1. 變量聲明提前
        示例1:

        此處的輸出是undefined,并沒有報錯,這是因為在前面我們提到的函數(shù)內的聲明在函數(shù)體內始終可見,上面的函數(shù)等效于:

        注意,如果忘記var,那么變量就被聲明為全局變量了。

        2. 沒有塊級作用域

        和其他我們常用的語言不同,在Javascript中沒有塊級作用域:

        輸出10 } console.log(j);//輸出1 }

        在javascript中變量的作用范圍是函數(shù)級的,即在函數(shù)中所有的變量在整個函數(shù)中都有定義,這也帶來了一些我們稍不注意就會碰到的“潛規(guī)則”:

        在①處輸出的值竟然是undefined,簡直喪心病狂啊,我們已經(jīng)定義了全局變量的值啊,這地方不應該為hello嗎?其實,上面的代碼等效于:

        聲明提前、全局變量優(yōu)先級低于局部變量,根據(jù)這兩條規(guī)則就不難理解為什么輸出undefined了。

        作用域鏈

        在javascript中,每個函數(shù)都有自己的執(zhí)行上下文環(huán)境,當代碼在這個環(huán)境中執(zhí)行時,會創(chuàng)建變量對象的作用域鏈,作用域鏈是一個對象列表或對象鏈,它保證了變量對象的有序訪問。
        作用域鏈的前端是當前代碼執(zhí)行環(huán)境的變量對象,常被稱之為“活躍對象”,變量的查找會從第一個鏈的對象開始,如果對象中包含變量屬性,那么就停止查找,如果沒有就會繼續(xù)向上級作用域鏈查找,直到找到全局對象中:

        作用域鏈的逐級查找,也會影響到程序的性能,變量作用域鏈越長對性能影響越大,這也是我們盡量避免使用全局變量的一個主要原因。

        閉包

        基礎概念
        作用域是理解閉包的一個前提,閉包是指在當前作用域內總是能訪問外部作用域中的變量。

        上面的示例在函數(shù)中返回了兩個閉包,這兩個閉包都維持著對外部作用域的引用,因此不管在哪調用總是能夠訪問外部函數(shù)中的變量。在一個函數(shù)內部定義的函數(shù),會將外部函數(shù)的活躍對象添加到自己的作用域鏈中,因此上面實例中通過內部函數(shù)能夠訪問外部函數(shù)的屬性,這也是javascript模擬私有變量的一種方式。

        注意:由于閉包會額外的附帶函數(shù)的作用域(內部匿名函數(shù)攜帶外部函數(shù)的作用域),因此,閉包會比其它函數(shù)多占用些內存空間,過度的使用可能會導致內存占用的增加。

        閉包中的變量

        在使用閉包時,由于作用域鏈機制的影響,閉包只能取得內部函數(shù)的最后一個值,這引起的一個副作用就是如果內部函數(shù)在一個循環(huán)中,那么變量的值始終為最后一個值。

        上面的程序并沒有按照我們預期的輸入1-5的數(shù)字,而是5次全部輸出了5。再來看一個示例:

        調用createClosure()[0]()返回的是5,createClosure()[4]()返回值仍然是5。通過以上兩個例子可以看出閉包在帶有循環(huán)的內部函數(shù)使用時存在的問題:因為每個函數(shù)的作用域鏈中都保存著對外部函數(shù)(timeManage、createClosure)的活躍對象,因此,他們都引用著同一變量i,當外部函數(shù)返回時,此時的i值為5,所以內部的每個函數(shù)i的值也為5。
        那么如何解決這個問題呢?我們可以通過匿名包裹器(匿名自執(zhí)行函數(shù)表達式)來強制返回預期的結果:

        或者在閉包匿名函數(shù)中再返回一個匿名函數(shù)賦值:

        輸出1,2,3,4,5 function createClosure() { var result = []; for (var i = 0; i < 5; i++) { result[i] = function(num) { return function() { console.log(num); } }(i); } return result; } //createClosure()[1]()輸出1;createClosure()[2]()輸出2

        無論是匿名包裹器還是通過嵌套匿名函數(shù)的方式,原理上都是由于函數(shù)是按值傳遞,因此會將變量i的值復制給實參num,在匿名函數(shù)的內部又創(chuàng)建了一個用于返回num的匿名函數(shù),這樣每個函數(shù)都有了一個num的副本,互不影響了。

        閉包中的this

        在閉包中使用this時要特別注意,稍微不慎可能會引起問題。通常我們理解this對象是運行時基于函數(shù)綁定的,全局函數(shù)中this對象就是window對象,而當函數(shù)作為對象中的一個方法調用時,this等于這個對象(TODO 關于this做一次整理)。由于匿名函數(shù)的作用域是全局性的,因此閉包的this通常指向全局對象window:

        調用object.getScope()()返回值為global而不是我們預期的local,前面我們說過閉包中內部匿名函數(shù)會攜帶外部函數(shù)的作用域,那為什么沒有取得外部函數(shù)的this呢?每個函數(shù)在被調用時,都會自動創(chuàng)建this和arguments,內部匿名函數(shù)在查找時,搜索到活躍對象中存在我們想要的變量,因此停止向外部函數(shù)中的查找,也就永遠不可能直接訪問外部函數(shù)中的變量了。總之,在閉包中函數(shù)作為某個對象的方法調用時,要特別注意,該方法內部匿名函數(shù)的this指向的是全局變量。

        幸運的是我們可以很簡單的解決這個問題,只需要把外部函數(shù)作用域的this存放到一個閉包能訪問的變量里面即可:

        內存與性能

        由于閉包中包含與函數(shù)運行期上下文相同的作用域鏈引用,因此,會產(chǎn)生一定的負面作用,當函數(shù)中活躍對象和運行期上下文銷毀時,由于必要仍存在對活躍對象的引用,導致活躍對象無法銷毀,這意味著閉包比普通函數(shù)占用更多的內存空間,在IE瀏覽器下還可能會導致內存泄漏的問題,如下:

        上面例子中匿名函數(shù)對外部對象target產(chǎn)生一個引用,只要是匿名函數(shù)存在,這個引用就不會消失,外部函數(shù)的target對象也不會被銷毀,這就產(chǎn)生了一個循環(huán)引用。解決方案是通過創(chuàng)建target.name副本減少對外部變量的循環(huán)引用以及手動重置對象:

        閉包中如果存在對外部變量的訪問,無疑增加了標識符的查找路徑,在一定的情況下,這也會造成性能方面的損失。解決此類問題的辦法我們前面也曾提到過:盡量將外部變量存入到局部變量中,減少作用域鏈的查找長度。

        總結:閉包不是javascript獨有的特性,但是在javascript中有其獨特的表現(xiàn)形式,使用閉包我們可以在javascript中定義一些私有變量,甚至模仿出塊級作用域,但閉包在使用過程中,存在的問題我們也需要了解,這樣才能避免不必要問題的出現(xiàn)。

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

        文檔

        深入理解javascript作用域和閉包_基礎知識

        深入理解javascript作用域和閉包_基礎知識:作用域 作用域是一個變量和函數(shù)的作用范圍,javascript中函數(shù)內聲明的所有變量在函數(shù)體內始終是可見的,在javascript中有全局作用域和局部作用域,但是沒有塊級作用域,局部變量的優(yōu)先級高于全局變量,通過幾個示例來了解下javascript中作用域的那些潛
        推薦度:
        標簽: js 理解 javascript
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top 主站蜘蛛池模板: 美女视频黄频a免费观看| 精品久久久久久无码免费| 亚洲五月丁香综合视频| 亚洲一区二区三区亚瑟| 麻豆安全免费网址入口| 青青草国产免费久久久下载 | 一区二区三区免费视频观看| 无码日韩精品一区二区免费暖暖| 亚洲国产精品免费观看| 国产乱子伦片免费观看中字| 亚洲欧洲日产国产综合网| 亚洲av无码专区在线电影| 久久久久久国产精品免费免费男同| 国产亚洲无线码一区二区| 亚洲av无码片vr一区二区三区| 暖暖日本免费在线视频| 亚洲国产av高清无码| 两个人看的www免费高清| 免费看又爽又黄禁片视频1000 | 国产精品亚洲专区无码牛牛| 日本免费人成视频在线观看| 日本一道综合久久aⅴ免费| 精品免费AV一区二区三区| 99精品视频在线视频免费观看 | 久久一区二区免费播放| 亚洲嫩草影院久久精品| 成人免费视频69| 亚洲AV无码成人精品区蜜桃| 日韩在线观看免费| 免费看国产一级片| a在线观看免费视频| 国产成人免费网站在线观看| 456亚洲人成影院在线观| 国产人成免费视频| 久久福利青草精品资源站免费| 国产亚洲成人久久| 亚洲精品无码成人| 色婷婷7777免费视频在线观看| 亚洲成a人片在线播放| 色偷偷噜噜噜亚洲男人| 亚洲精品国产精品乱码不卡√ |