2018-03-09關(guān)于js作用域蟀伸。

大家好蚀同,我是IT修真院成都分院第10期學(xué)員李勁宏缅刽,一枚正直純潔善良的web程序員,今天給大家分享一下JS作用域蠢络。

任何程序設(shè)計語言都有作用域的概念衰猛,簡單的說,作用域就是變量與函數(shù)的可訪問范圍刹孔,即作用域控制著變量與函數(shù)的可見性和生命周期啡省。在JavaScript中,變量的作用域有全局作用域和局部作用域兩種髓霞。

1.全局作用域(Global Scope)


在代碼中任何地方都能訪問到的對象擁有全局作用域卦睹,一般來說一下幾種情形擁有全局作用域:

var aName="123";

function doSomething(){

? ? var bName="456";

}

console.log(aName); //123

console.log(bName); //腳本錯誤

(2)所有末定義直接賦值的變量自動聲明為擁有全局作用域,例如:

function a1(){

? ? num = 5;

}

a1();

console.log(num); //? 5

3)所有window對象的屬性擁有全局作用域

一般情況下方库,window對象的內(nèi)置屬性都都擁有全局作用域分预,例如window.name、window.top等等薪捍。

1. 局部作用域(Local Scope)

和全局作用域相反,局部作用域一般只在固定的代碼片段內(nèi)可訪問到配喳,最常見的例如函數(shù)內(nèi)部酪穿,所有在一些地方也會看到有人把這種作用域成為函數(shù)作用域。

例如下列代碼中的bName和函數(shù)innerSay都只擁有局部作用域:

function doSomething(){

? ? var bName="李云龍";

? ? function innerSay(){

? ? ? ? alert(bName);

? ? }

? ? innerSay();

}

alert(bName); //腳本錯誤innerSay(); //腳本錯誤

閉包

如何從外部讀取局部變量晴裹?? ? ? ? ? ? 出于種種原因被济,我們有時候需要得到函數(shù)內(nèi)的局部變量。但是涧团,前面已經(jīng)說過了只磷,正常情況下,這是辦不到的泌绣,只有通過變通方法才能實現(xiàn)钮追。? ? ? ? ? ? 那就是在函數(shù)的內(nèi)部,再定義一個函數(shù)阿迈。

 function f1(){

? ? ? ? ? ? ? ?     var n=999;

? ? ? ? ? ? ? ?     function f2(){

? ? ? ? ? ? ? ?       alert(n); // 999? ? ? ? ? ? ? ?     }

? ? ? ? ? ? ? ?   }

在上面的代碼中元媚,函數(shù)f2就被包括在函數(shù)f1內(nèi)部,這時f1內(nèi)部的所有局部變量苗沧,對f2都是可見的刊棕。但是反過來就不行,f2內(nèi)部的局部變量待逞,對f1就是不可見的甥角。這就是Javascript語言特有的"鏈?zhǔn)阶饔糜?結(jié)構(gòu)(chain scope),子對象會一級一級地向上尋找所有父對象的變量识樱。所以嗤无,父對象的所有變量震束,對子對象都是可見的,反之則不成立翁巍。

? ? ? ? ? ? 既然f2可以讀取f1中的局部變量驴一,那么只要把f2作為返回值,我們不就可以在f1外部讀取它的內(nèi)部變量了嗎灶壶!  function f1(){

? ? ? ? ? ? ? ?     var n=999;

? ? ? ? ? ? ? ?     function f2(){

? ? ? ? ? ? ? ?       alert(n);

? ? ? ? ? ? ? ?     }

? ? ? ? ? ? ? ?     return f2;

? ? ? ? ? ? ? ?   }

? ? ? ? ? ? ? ?   var result=f1();

? ? ? ? ? ? ? ?   result(); // 999? ? ? ? ? ?

閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)肝断。 由于在Javascript語言中,只有函數(shù)內(nèi)部的子函數(shù)才能讀取局部變量驰凛,因此可以把閉包簡單理解成"定義在一個函數(shù)內(nèi)部的函數(shù)"胸懈。 所以,在本質(zhì)上恰响,閉包就是將函數(shù)內(nèi)部和函數(shù)外部連接起來的一座橋梁趣钱。

閉包的注意點

1)由于閉包會使得函數(shù)中的變量都被保存在內(nèi)存中,內(nèi)存消耗很大胚宦,所以不能濫用閉包首有,否則會造成網(wǎng)頁的性能問題,在IE中可能導(dǎo)致內(nèi)存泄露枢劝。解決方法是井联,在退出函數(shù)之前,將不使用的局部變量全部刪除您旁。? ? ? ? ? ? 2)閉包會在父函數(shù)外部烙常,改變父函數(shù)內(nèi)部變量的值。所以鹤盒,如果你把父函數(shù)當(dāng)作對象(object)使用蚕脏,把閉包當(dāng)作它的公用方法(Public Method),把內(nèi)部變量當(dāng)作它的私有屬性(private value)侦锯,這時一定要小心驼鞭,不要隨便改變父函數(shù)內(nèi)部變量的值。


小課堂提問:

1.閉包的使用場景尺碰。?

<1>通過循環(huán)給頁面上多個DOM節(jié)點綁定時間终议,在JS中可以采用“立即執(zhí)行函數(shù)”的方式創(chuàng)建作用域。

<2>封裝變量葱蝗,閉包可以將一些不希望暴露在全局的變量封裝成私有變量穴张。

<3>延續(xù)局部變量的壽命。

什么是“自執(zhí)行函數(shù)”两曼?

我們先來說一下這個函數(shù)在叫法上的爭議皂甘。實際上不同的人對自執(zhí)行函數(shù)的理解不太一樣,第一種理解是悼凑,自執(zhí)行即自動執(zhí)行偿枕,也就是大家平時所謂的立即執(zhí)行函數(shù)璧瞬。

還有一種理解,即自執(zhí)行函數(shù)是在函數(shù)內(nèi)部執(zhí)行函數(shù)本身渐夸,即我們平時常說的遞歸函數(shù)嗤锉。不管是哪種理解,我們都沒必要去糾結(jié)叫法上的準(zhǔn)確與否墓塌,因為相比于自執(zhí)行函數(shù)瘟忱,立即執(zhí)行函數(shù)和遞歸函數(shù)這兩種叫法是我們更加熟悉的,實際上平時也很少會看到自執(zhí)行函數(shù)這種叫法苫幢。立即執(zhí)行函數(shù)和遞歸函數(shù)都很重要访诱。

閉包的優(yōu)點和缺點:

優(yōu)點:?

1.保護(hù)函數(shù)內(nèi)的變量安全,加強了封裝性?

2.在內(nèi)存中維持一個變量(用的太多就變成了缺點,占內(nèi)存)?

閉包之所以會占用資源是當(dāng)函數(shù)a執(zhí)行結(jié)束后, 變量i不會因為函數(shù)a的結(jié)束而銷毀, 因為b的執(zhí)行需要依賴a中的變量韩肝。

不適合場景:?

返回閉包的函數(shù)是個非常大的函數(shù)触菜。

閉包的典型框架應(yīng)該就是jquery了。?

閉包是javascript語言的一大特點哀峻,主要應(yīng)用閉包場合主要是為了:設(shè)計私有的方法和變量涡相。?

這在做框架的時候體現(xiàn)更明顯,有些方法和屬性只是運算邏輯過程中的使用的剩蟀,不想讓外部修改這些屬性漾峡,因此就可以設(shè)計一個閉包來只提供方法獲取。?

閉包的缺點就是常駐內(nèi)存喻旷,會增大內(nèi)存使用量,使用不當(dāng)很容易造成內(nèi)存泄露牢屋。

邏輯連續(xù)且预,當(dāng)閉包作為另一個函數(shù)調(diào)用的參數(shù)時,避免你脫離當(dāng)前邏輯而單獨編寫額外邏輯烙无。

方便調(diào)用上下文的局部變量锋谐。

加強封裝性,第2點的延伸截酷,可以達(dá)到對變量的保護(hù)作用涮拗。

缺點:

閉包有一個非常嚴(yán)重的問題,那就是內(nèi)存浪費問題迂苛,這個內(nèi)存浪費不僅僅因為它常駐內(nèi)存三热,更重要的是,對閉包的使用不當(dāng)會造成無效內(nèi)存的產(chǎn)生三幻。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末就漾,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子念搬,更是在濱河造成了極大的恐慌抑堡,老刑警劉巖摆出,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異首妖,居然都是意外死亡偎漫,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門有缆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來象踊,“玉大人,你說我怎么就攤上這事妒貌⊥ㄎ#” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵灌曙,是天一觀的道長菊碟。 經(jīng)常有香客問我,道長在刺,這世上最難降的妖魔是什么逆害? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮蚣驼,結(jié)果婚禮上魄幕,老公的妹妹穿的比我還像新娘。我一直安慰自己颖杏,他們只是感情好纯陨,可當(dāng)我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著留储,像睡著了一般翼抠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上获讳,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天阴颖,我揣著相機與錄音,去河邊找鬼丐膝。 笑死量愧,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的帅矗。 我是一名探鬼主播偎肃,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼浑此!你這毒婦竟也來了软棺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤尤勋,失蹤者是張志新(化名)和其女友劉穎喘落,沒想到半個月后茵宪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡瘦棋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年稀火,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赌朋。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡凰狞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出沛慢,到底是詐尸還是另有隱情赡若,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布团甲,位于F島的核電站逾冬,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏躺苦。R本人自食惡果不足惜身腻,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望匹厘。 院中可真熱鬧嘀趟,春花似錦、人聲如沸愈诚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽炕柔。三九已至酌泰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間汗唱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工丈攒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留哩罪,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓巡验,卻偏偏與公主長得像际插,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子显设,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執(zhí)行單位為行(line)框弛,也就是一...
    悟名先生閱讀 4,131評論 0 13
  • 閉包(closure)是Javascript語言的一個難點,也是它的特色捕捂,很多高級應(yīng)用都要依靠閉包實現(xiàn)瑟枫。 一斗搞、變量...
    zock閱讀 1,075評論 2 6
  • 關(guān)于 javascript 閉包的一些思考 作用域 詞法作用域 函數(shù)作用域 塊作用域 閉包 什么是作用域? 作用域...
    _panda閱讀 274評論 0 1
  • 東漢末年,群雄并起慷妙。逐鹿中原僻焚,斗力更斗智,說到底還是人才之爭膝擂。 其時傳說位于智極者有二虑啤,所謂“伏龍鳳雛,二人得一架馋,...
    煙花英雄閱讀 694評論 0 3
  • 給我一點愛狞山,我想為你抹平眉頭的皺紋。 給我一點愛叉寂,我想為你分擔(dān)你的憂愁 給我一點愛萍启,我想和你一起看日出。 給我一點...
    莫離痕閱讀 210評論 0 2