如果想要學好Javascript,有三個地方必須要認真掌握:兩鏈一包
兩鏈:作用域鏈與原型鏈
一包:Javascript中的閉包
在Javascript中沒有塊級作用域,對作用域的劃分都是通過function函數來實現的。在函數外部的區域就是全局作用域,在函數內部的區域就是局部作用域。
在全局作用域中定義的變量就是"全局變量"
在局部作用域中定義的變量我們就稱之為"局部變量"
但是全局變量與局部變量也是相對而言的,也會存在以下特殊形式:
在全局作用域中可以引入全局變量,在局部作用域中即可以引用全局變量也可以引用局部變量。
但是在全局作用域是不能訪問局部變量的,如下圖所示:
主要原因有二:
① 作用域不允許
② 受到Javascript垃圾回收機制的影響
Javascript垃圾回收機制:
當函數執行完畢後,其內部的所有局部變量都會自動被內存所回收,這就是垃圾回收機制。
?
問題:為什麼在局部作用域中可以引用全局變量呢?
答:受到作用域鏈的影響
在局部作用中,引用一個變量後,系統會自動在當前作用域中尋找var的聲明語句,如果找到則直接使用,否則繼續向上一級作用域中去尋找var的聲明語句,如未找到,則繼續向上級作用域中尋找…直到全局作用域中如還未找到var的聲明語句則自動在全局作用域中聲明該變量。我們把這種鏈式的查詢關系就稱之為"作用域鏈"。
?
例1:使用作用域鏈的原則解析以下代碼
運行結果:10
解析:當我們執行display函數時,系統會自動執行第13行代碼,由於在局部作用域中引用了一個變量i,所以根據作用域鏈的原則,系統首先在當前作用域中尋找var的聲明語句,但未找到,所以繼續向上一級作用域中尋找var的聲明語句,在全局作用域中找到了var的聲明語句,所以直接彈出結果10。
?
例2:使用作用域鏈原則解析以下代碼的執行結果
運行結果:100
解析:系統首先在全局作用域中定義一個全局變量var i = 10,然後在12行代碼中定義一個函數fn1,然後繼續向下執行,在第24行執行fn1函數,然後進入到fn1函數內部執行代碼,在第13行中定義一個局部變量var i=100,然後繼續定義fn2函數並在第22行執行,然後執行fn2函數並在其內部定義並執行fn3函數,由於在fn3函數內部使用了變量i,所以其會自動在當前作用域中尋找var的聲明語句,未找到則進入到fn2中去尋找,也未找到,繼續向上一級fn1函數中尋找,找到var i=100,所以直接使用該變量,整個程序的執行結果為100。
?
例3:改進上題,說出程序的執行結果
在Javascript中,代碼都是從上往下一行一行執行的,所以以上代碼首先在第10行定義一個全局變量i等於10,然後在12行代碼定義一個fn1函數並在24行執行,然後進入到fn1函數的內部繼續執行,由於在第13行使用了一個變量i,但是其並未聲明,所以根據作用域鏈的原則,系統會自動在當前作用域中尋找var的聲明語句,未找到則自動向上一級作用域中去尋找,找到了var i = 10則直接使用,覆蓋全局中的i,然後代碼繼續向下執行定義fn2並執行,定義fn3並執行,由於在fn3函數的內部,又引入了變量i,根據作用域鏈的原則,繼續向上尋找,直到全局作用域,由於全局中的變量i已被覆蓋為100,所以最終結果為100。