歡迎光臨
每天分享高質量文章

Javascript之旅——第一站:從變數說起

工作這幾年,js學的不是很好,正好週末有些閑時間,索性買本《js權威指南》,大名鼎鼎的犀牛書,好好的把js深入的看一看。買過這本書的第一印象就是賊厚,不過後面有一半部分都是參考手冊。

一:作用域

說起變數第一個要說到的肯定就是作用域,正是因為不熟悉JS的作用域,往往就會把面向物件的作用域張冠李戴,畢竟有些東西總是習慣性的這樣,但是並不是每次照搬都是可以的,那麼下一個問題就來了,js到底是什麼作用域,當然是函式作用域了,我們的瀏覽器就是一個被實體

化的window物件,如果在window下定義一個name欄位,那麼name欄位就具有window這個函式作用域,也就是在window下都是可以訪問的,如果在window下定義一個function ctrip,然後裡面再定義一個name,那麼這個新定義的name只能在ctrip函式下通用,而老的name繼續window下通用,舉個例子。

從圖中可以看出兩點:

1: 在window下定義了一個name,居然還可以在function下定義一個重名的name,這個在C#裡面是不可想象的。

2:在JS下就可以做到眼瞎,它只認自己的作用域,所以就出現了第一個”second”,你可能覺得這個沒有什麼稀奇的地方,這是因為可能你還沒有真正理解什麼是函式作用域,解析器在執行ctrip的時候,第一件事情就是尋找ctrip下的所有區域性變數,然後再執行後續陳述句,既然是先尋找,那麼var name=”second”這條陳述句定義在ctrip中任何位置都是可以的,下麵我們把陳述句調換過來。

可以看到在ctrip函式下,第一個console.log輸出的是undefined,這個結果可以證實,確實做了第一件事情是收集到了name這個區域性變數,可能有人說為什麼沒有變成”second“,那是因為初始化操作必須是逐陳述句執行,所以在ctrip函式中執行console.log(name)時,此時解析器只知道有一個未賦值的變數name,所以就console的時候就是undefined了。

二:作用域鏈

從上面的這個例子中我們也很清楚的知道了,在function中定義的變數只具有function範圍內的作用域,同時我們也看到上面這個例子只是一層巢狀,window是個大的function,裡面是一個ctrip的function,同樣的道理也可以延伸到多層巢狀,比如三層,四層。。。。N層,這些層就形成了一個鏈式結構。

從圖中可以看到,我在ctrip下再定義了一個plane函式,這樣的話就有三層了,輸出的結果也是我們希望看到的,每層的name只在自己的作用域範圍內生效,但是下麵有一個問題來了,有一天我傻逼了,在定義plane的函式時,把 var name=”third” 中的var忘記寫了,那麼這個時候,plane中的name到底是什麼值呢? 是first還是second呢?

var name=”first”;

function ctrip(){

var name=”second”;

function plane(){

name=”third”;

console.log(name);

}

plane();

console.log(name);

}

ctrip();

console.log(name);

現在就是考驗你是否真的懂了作用域鏈,仔細想想會發現,當程式碼執行到plane函式中的name=”third“時,發現plane函式中並沒有name這個區域性變數,恰好程式碼又在ctrip這個大函式中,所以解析器就會回溯到ctrip函式中尋找name,發現果然有name,這個時候就把ctrip的name修改成了”third“。

又有一天,我喝多了酒又傻逼了一回,在定義plane函式的時候,把name=”third” 錯寫成了 nam=”third”; 丟了一個e,你可以說是酒精的問題,又不是我程式碼的問題。那麼這個時候解析器該怎麼處理呢?同樣的道理,在回溯時,發現ctrip沒有,再回溯到頂層的window下,發現還是沒有,這個時候解析器做了這樣的處理,既然整個鏈中都沒有,你又賦值了,我總不能給你報錯,那多尷尬呀,就索性給你在window下隱式的定義一個nam變數,這個時候nam其實就是全域性變數了。我們可以在window頂層console一下nam看看。

好了,關於變數的東西也就這麼多了,沒什麼稀奇的,理解了就沒什麼意思了。

來自:一線碼農的部落格

連結:http://www.cnblogs.com/huangxincheng/p/4116071.html

贊(0)

分享創造快樂