日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

(转)JavaScript: 零基础轻松学闭包(1)

發(fā)布時間:2024/10/12 javascript 72 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (转)JavaScript: 零基础轻松学闭包(1) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
  • 閉包是什么?

初學(xué)javascript的人,都會接觸到一個東西叫做閉包,聽起來感覺很高大上的。網(wǎng)上也有各種五花八門的解釋,其實(shí)我個人感覺,沒必要用太理論化的觀念來看待閉包。

事實(shí)上,你每天都在用閉包,只是你不知道罷了。

比如:

var cheese = '奶酪';var test = function(){alert(cheese); }

?

OK,你已經(jīng)寫了一個閉包。

  • 函數(shù)也是一個數(shù)據(jù)類型

變量 cheese 是在全局作用域中的一個變量,當(dāng)你創(chuàng)建了一個 test 函數(shù),那么,test 和 cheese 就共享一個全局作用域。

你要額外明白的一點(diǎn)是,在js中,函數(shù)和變量本質(zhì)上是一個東西。函數(shù)也是一個數(shù)據(jù)類型。

從上面的定義中也能看出來這一點(diǎn)。你要是不相信的話,我們來看一下咯。

alert(cheese); alert(test);

讓我們再來看看 test 和 cheese各是什么類型:

alert(typeof test); alert(typeof cheese);

看到了吧,只是類型不同而已,他們都是數(shù)據(jù)類型。

唯一的不同點(diǎn)就是,函數(shù)類型的 test 可以擁有自己內(nèi)部邏輯,而string類型的 cheese 只能存放一個字面值,這就是區(qū)別,僅此而已。

一目了然了,唯一不同的就是普通變量是字面值一樣的存在,而函數(shù)需要打個括號才能執(zhí)行而已。

你看,我現(xiàn)在打一個括號:

test();

打了括號,才會執(zhí)行函數(shù)里面的邏輯。

  • 作用域

讓我們回到閉包,現(xiàn)在將之前的代碼做一個小小的變動:

var cheese = '奶酪'; var test = function(){alert(cheese); }function test2(){var cheese = null;test(); }test2();

?

那么,你覺得現(xiàn)在 alert 出來的是 null 還是奶酪呢?

思考一下。。。

對的,彈出來的還是奶酪。

之前已經(jīng)說過了,函數(shù) test 和 變量 cheese 同處于一片藍(lán)天下 -- 同一個作用域。

函數(shù) test 和 變量 cheese 共同享有的作用域叫做全局作用域,就好像地球一樣,我們所有的人都享有這個地球,能夠在這里呼吸,吃飯,玩耍。

對test而言,他能訪問到的作用域只有它本身的閉包和全局作用域:

Paste_Image.png

也就是說,正常情況下他訪問不到其他閉包里的內(nèi)容,在 test2 里面定義的變量跟它沒有半毛錢關(guān)系,所以彈出來的 cheese 依舊是全局作用域里的 cheese。

函數(shù)可以創(chuàng)造自己的作用域。

我們剛才定義了一個 test 函數(shù),{ } 包裹起來的部分就形成了一個新的作用域,也就是所謂的閉包。

其實(shí)你深刻了解了作用域的原理后,閉包也就理解了。

就好比地球是一個全局作用域,你自己家的房子是一個函數(shù),你的房子是私人空間,就是一個局部作用域,也就是你自己建了一個閉包!

你透過窗戶可以看見外邊的景色,比如院子里的一棵芭蕉樹,你于是通過眼鏡觀察看到了芭蕉樹的顏色,高度,枝干的粗細(xì)等等。

這一棵芭蕉樹相當(dāng)于一個全局變量,你在自己的閉包內(nèi)可以訪問到它的數(shù)據(jù)。

所以,在這個例子中,test 就是一個房子,在里面可以通過窗戶訪問到全局作用域中的奶酪 —— 變量 cheese。

也就是說,cheese 在被 test 訪問到的時候,就進(jìn)入了它的閉包。

這樣解釋,你是否覺得好理解一點(diǎn)呢?

現(xiàn)在你是否可以理解一開始我說,閉包這東西其實(shí)我們天天都在用的意思了呢?

我們給出閉包的第一個注解:

1. 閉包就是在函數(shù)被創(chuàng)建的時候,存在的一個私有作用域,并且能夠訪問所有的父級作用域。

回到剛才的例子:

var cheese = '奶酪'; var test = function(){alert(cheese); }function test2(){var cheese = null;test(); }

?

在這個例子中,test 和 test2 各自享有一個作用域,對不對?而且他們互相不能訪問。比如,我在 test 中定義的一個變量,test2就無法直接訪問。

var test = function(){var i = 10; }function test2(){alert(i); }test2();

?

像這樣,一旦執(zhí)行 test2 函數(shù),編譯就不通過,因?yàn)樵?test2的閉包內(nèi),根本找不到變量 i 。它首先會在自己的閉包內(nèi)尋找 i,找不到的話就去父級作用域里找,這邊的父級就是全局作用域,很遺憾,還是沒有。這就是所謂的作用域鏈,它會一級一級往上找。如果找到最頂層,還是找不到的話,就會報錯了。

在這里,還有一個需要注意的點(diǎn)就是:如果某一個閉包中對全局作用域(或父級作用域)中的變量進(jìn)行了修改,那么任何引用該變量的閉包都會受到牽連。

這的確是一個需要注意的地方。

舉個例子

var cheese = '奶酪';var test = function(){cheese = '奶酪被偷吃了!' }function test2(){alert(cheese); } test(); test2();

?

結(jié)果是:

Paste_Image.png

很有趣,是不是呢?

當(dāng)我們在定義一個函數(shù),就產(chǎn)生了一個閉包,如果這個函數(shù)里面又有若干的內(nèi)部函數(shù),就是閉包嵌套著閉包。

像這樣:

function house(){var footBall = '足球';/* 客廳 */function livingRoom(){var table = '餐桌';var sofa = '沙發(fā)';alert(footBall);}/* 臥室 */function bedRoom(){var bed = '大床';}livingRoom(); }house();

?

函數(shù)house是一個閉包,里面又定義了兩個函數(shù),分別是livingRoom客廳,和bedRoom臥室,它們各自形成一個自己的閉包。對它們而言,父級作用域就是house。

如果我們希望在客廳里踢足球,在livingRoom函數(shù)執(zhí)行的時候,它會先在自己的閉包中找足球,如果沒找到,就去house里面找。一層一層往上找,直至找到了為止。當(dāng)然,這個例子可能不是很恰當(dāng)。但起碼展示了作用域,閉包之間的聯(lián)系。

再說明一下, 閉包就是在函數(shù)被創(chuàng)建的時候,存在的一個私有作用域,并且能夠訪問所有的父級作用域。因此,從理論上講,任何函數(shù)都是一個閉包!



作者:剽悍一小兔
鏈接:https://www.jianshu.com/p/6f5833e261ac
來源:簡書
簡書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請聯(lián)系作者獲得授權(quán)并注明出處。

轉(zhuǎn)載于:https://www.cnblogs.com/dragonwave/p/9273580.html

總結(jié)

以上是生活随笔為你收集整理的(转)JavaScript: 零基础轻松学闭包(1)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。