js便簽筆記(12)——瀏覽TOM大叔博客的學(xué)習(xí)筆記 part2
1. 前言
昨天寫了《js便簽筆記(11)——瀏覽TOM大叔博客的學(xué)習(xí)筆記 part1》,簡單記錄了幾個問題。part1的重點還是在于最后那個循環(huán)創(chuàng)建函數(shù)的問題,也就是多個子函數(shù)公用一個閉包數(shù)據(jù)的問題。如果覺得有興趣,可以再重新翻出來看看。
今天繼續(xù)把剩下的問題寫完。
2. 作用域鏈
學(xué)js的人,即使初級入門的也都知道“原型鏈”,但是“作用域鏈”,可能好多人沒有聽說過。大部分人都知道或者聽說過“閉包”,但是可能有好多人不知道閉包其實和作用域鏈有莫大的聯(lián)系。如果理解閉包不從作用域鏈開始理解,那么你就只能理解閉包的皮毛。
我也是從TOM大叔的這些博客中才了解到作用域鏈的,之前也看過了許多本書籍,都沒有很清晰的展開作用域鏈這個概念。其實作用域鏈簡單說來也好理解,如下代碼:
var x = 10; function fn() { var y = 20; return function () { var z = 30 console.log(x + y + z); } }
上面代碼中,如果想要打印 x+y+z 的值,就必須要遍歷三個層次的上下文環(huán)境或者作用域,這其實和原型鏈的結(jié)構(gòu)表現(xiàn)形式類似。但要細(xì)細(xì)將來,連同閉包圖文并茂的說明白,需要很多內(nèi)容。
此處不再深入進去,以后有機會再另起一篇詳細(xì)介紹。
3. 二維鏈查找
上文講到通過作用域練向上查找變量,實際在查找變量的過程中,是使用“二維鏈查找”——“作用域鏈” + “原型鏈”。看如下代碼:
Object.prototype.x = 10; function fn() { var y = 20; return function () { var z = 30 console.log(x + y + z); } }
這份代碼跟上文中演示作用域鏈的代碼差不多,但是它卻通過 Object.prototype.x = 10; 這么一句話,表現(xiàn)出了原型鏈在其中的作用。
因此,在查找變量值時,是同時兼顧原型鏈和作用域鏈兩個方向的,即“二維鏈查找”。
4. 獨立作用域只能通過函數(shù)來創(chuàng)建
這句話的下半句是——不能通過if/for等語句塊來創(chuàng)建。后半句大家可能知道,但是它的本質(zhì)確實前半句——獨立作用域只能通過函數(shù)來創(chuàng)建(除了獨立作用域之外,剩下的就是全局作用域)。既然獨立作用域只能通過函數(shù)來創(chuàng)建,那么函數(shù)中任何地方的自由變量就都是函數(shù)層級的,因此,以下代碼希望不要再次出現(xiàn):
5. 隱式全局變量的本質(zhì)
var a = 10; b = 20;
以上兩句代碼,看似都是聲明兩個全局變量,但是按照TOM大叔說的,只有var才能聲明一個變量,也就是 var a = 10; 是真正的聲明變量。
而下一句 b = 20,其實是相當(dāng)于設(shè)置window的一個屬性值而已。
因此,第一句的本質(zhì)是聲明一個全局變量;第二句的本質(zhì)是設(shè)置window的一個屬性值。
當(dāng)然,不推薦用第二句的形式。
6. 函數(shù)聲明和函數(shù)表達(dá)式的不同
js定義函數(shù)的方法有多種,但看看以下這段代碼:
fn(); var fn = function() { //函數(shù)表達(dá)式 alert(123); // 報錯 } //------ fn(); function fn() { //函數(shù)聲明 alert(123); // 123 }
兩種函數(shù)定義方式,卻得出不一樣的結(jié)果。
此處我當(dāng)時沒有詳細(xì)看,因為這樣使用的情況不是很多,所以就沒有過深入的細(xì)看,只是做了個標(biāo)記。如果有了解的朋友,不放解釋一下。
7.js使用靜態(tài)作用域
在part1中講過,當(dāng)一個函數(shù)作為參數(shù)被傳入,后者作為一個值被返回的時候,連同它一塊被傳遞的,是它的作用域。也就是咱們常說的閉包。且看如下代碼:
var x = 10; function foo() { alert(x); } (function (funarg) { var x = 20; funarg(); // 10, 不是20 })(foo);
foo是一個函數(shù),把它作為參數(shù)傳入進另一個函數(shù)中執(zhí)行,連同一起傳遞的,是foo的作用域。而foo使用的是靜態(tài)作用域,其中的變量x在傳遞的時候已經(jīng)被靜態(tài)賦值,不會受其他環(huán)境下x變量的影響。
這個道理也同樣適用于函數(shù)作為返回值。如下:
function fn() { var x = 10; return function () { alert(x); } } var ret = fn(); var x = 20; ret(); // 10,不是20
更多內(nèi)容請關(guān)注我的微博

浙公網(wǎng)安備 33010602011771號