摘要:吐槽一下,閉包這個詞的翻譯真是有很大的誤解性啊要說閉包,要先說下詞法作用域。閉包兩個作用通過閉包,在外部環境訪問內部環境的變量。閉包使得函數可以繼續訪問定義時的詞法作用域。
閉包是真的讓人頭暈啊,看了很久還是覺得很模糊。只能把目前自己的一些理解先寫下來,這其中必定包含著一些錯誤,待日后有更深刻的理解時再作更改。
吐槽一下,閉包這個詞的翻譯真是有很大的誤解性啊……
要說閉包,要先說下詞法作用域。
詞法作用域簡單來說,詞法作用域就是定義在詞法階段的作用域。換句話說,詞法作用域是由你在寫代碼時將變量和塊作用域寫在哪里來決定的。閉包 關于閉包無論函數在哪里被調用,也無論它如何被調用,它的詞法作用域都只由函數被聲明時所處的位置決定。
當函數可以記住并訪問所在的詞法作用域,即使函數是在當前詞法作用域之外執行,這時就產生了閉包。
作者:Cat Chen
閉包就是由函數創造的一個詞法作用域,里面創建的變量被引用后,可以在這個詞法環境之外自由使用。
閉包通常用來創建內部變量,使得這些變量不能被外部隨意修改,同時又可以通過指定的函數接口來操作。
function foo(){ var a=2; function bar(){ console.log(a); } return bar; } var baz=foo(); baz();//2——閉包
兩個作用:
(1):通過閉包,在外部環境訪問內部環境的變量。
(2):使得這些變量一直保存在內存中,不會被垃圾回收。
上面的代碼例子中,函數在定義時的詞法作用域以外的地方被調用。閉包使得函數可以繼續訪問定義時的詞法作用域。//?
調用的方式不僅僅只有以上代碼中的通過不同的標識符引用調用其內部的函數,
但是不管通過什么手段將內部函數傳遞到所在的詞法作用域以外,它都會持有對原始定義作用域的引用,無論在何處執行這個函數都會使用閉包。循環和閉包
for (var i=1;i<=5;i++){ setTimeout(function timer(){ console.log(i); },i*1000); }
正常預想下,上面這段代碼我們以為是分別輸出數字1-5,每秒一個。
但實際上,運行時輸出的卻是每秒輸出一個6,一共五次。
原因是,延遲函數的回調會在循環結束時才執行。
根據作用域的工作原理,循環中的五個函數是在各個迭代中分別定義的,但是它們都被封閉在一個共享的全局作用域中,實際上只有一個i。
我們可以通過IIFE創建作用域。(IIFE會通過聲明并立即執行一個函數來創建作用域)。
for (var i=1;i<=5;i++){ (funtion(){ setTimeout(function timer(){ console.log(i); },i*1000); })(); }
但是這樣創建的作用域里是空的,需要有自己的變量:
for (var i=1;i<=5;i++){ (funtion(){ var j=i; setTimeout(function timer(){ console.log(j); },j*1000); })(); }
改進得到:
for (var i=1;i<=5;i++){ (funtion(j){ setTimeout(function timer(){ console.log(j); },j*1000); })(i); }
ES6引入的let在循環中不止會被聲明一次,在每次迭代都會聲明:
for (let i=1;i<=5;i++){ setTimeout(function timer(){ console.log(i); },i*1000); }應用場景:模塊
模塊也是利用了閉包的一個強大的代碼模式。
function CoolModule(){ var something="cool"; var anothor=[1,2,3]; function doSomething(){ console.log(something); } function doAnthor(){ console.log(anothor.join("!")); } return{ doSomethig:doSomething, doAnothor:doAnother }; } var foo=CoolMOdule(); foo.doSomething();//cool foo.doAnother();//1!2!3
模塊有2個主要特征:關于模塊的引入
(1):為創建內部作用域而調用了一個包裝函數;
(2):包裝函數的返回值必須至少包括一個對內部函數的引用,這樣就會創建涵蓋整個包裝函數內部作用域的閉包。
import可以將一個模塊中的一個或多個API導入到當前作用域中,并分別綁定在一個變量上;
module會將整個模塊的API導入并綁定到一個變量上;
export會將當前模塊的一個標識符導出為公共API。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95871.html
摘要:寫在前面對于一個前端開發者,應該沒有不知道作用域的。欺騙詞法作用域有兩個機制可以欺騙詞法作用域和。關于你不知道的的第一部分作用域和閉包已經結束了,但是,更新不會就此止住未完待續 這是《你不知道的JavaScript》的第一部分。 本系列持續更新中,Github 地址請查閱這里。 寫在前面 對于一個前端開發者,應該沒有不知道作用域的。它是一個既簡單有復雜的概念,簡單到每行代碼都有它的影子...
摘要:詞法作用域的查找規則是閉包的一部分。因此的確同閉包息息相關,即使本身并不會真的使用閉包。而上面的創建一個閉包,本質上這是將一個塊轉換成一個可以被關閉的作用域。結合塊級作用域與閉包模塊這個模式在中被稱為模塊。 你不知道的JS(上卷)筆記 你不知道的 JavaScript JavaScript 既是一門充滿吸引力、簡單易用的語言,又是一門具有許多復雜微妙技術的語言,即使是經驗豐富的 Jav...
摘要:理解作用域在引擎看來是兩個完全不同的聲明。在循環中使用閉包閉包是函數和聲明該函數的詞法環境的組合。回到我們上面說的在自己定義的作用域以外的地方執行,這里聲明的是全局變量,使用全局變量不構成閉包。 第一章:作用域是什么 程序中變量存儲在哪里,需要是怎么找到它,這就需要設計一套存儲以及能方便的找到它的規則,這個規則就是作用域 編譯原理 JavaScript 是一門編譯語言,它與傳統編譯語言...
摘要:詞法作用域定義在詞法階段的作用域由你在寫代碼時將變量和塊作用域寫在哪來決定的,因此當詞法分析器處理代碼時會保持作用域不變。欺騙詞法作用域在詞法分析器處理過后依然可以修改作用域。 你不知道的JS(上卷)筆記 你不知道的 JavaScript JavaScript 既是一門充滿吸引力、簡單易用的語言,又是一門具有許多復雜微妙技術的語言,即使是經驗豐富的 JavaScript 開發者,如果沒...
摘要:最近剛剛看完了你不知道的上卷,對有了更進一步的了解。你不知道的上卷由兩部分組成,第一部分是作用域和閉包,第二部分是和對象原型。附錄詞法這一章并沒有說明機制,只是介紹了中的箭頭函數引入的行為詞法。第章混合對象類類理論類的機制類的繼承混入。 最近剛剛看完了《你不知道的 JavaScript》上卷,對 JavaScript 有了更進一步的了解。 《你不知道的 JavaScript》上卷由兩部...
閱讀 2570·2021-11-23 09:51
閱讀 3120·2019-08-30 15:54
閱讀 1070·2019-08-30 14:14
閱讀 3542·2019-08-30 13:59
閱讀 1393·2019-08-29 17:09
閱讀 1468·2019-08-29 16:24
閱讀 2848·2019-08-29 15:43
閱讀 911·2019-08-29 12:45