定義在詞法階段的做用域,開始時,編譯器作語法分析的時候,確認js裏各個詞法所在的做用域。
js裏只有全局做用域和函數做用域,這裏簡單介紹下js的做用域。異步
看下面代碼:函數
var a = 1; var b = 0; function foo() { var a = 2; console.log(a); //2 console.log(b); //0 } foo(); console.log(a); //1
一、在foo函數裏,在console.log(a),對a進行RHS查詢,發如今當前做用域存在變量a,若是foo裏沒有a就往上一層(全局)去查找
二、在foo函數裏,在console.log(b),對b進行RHS查詢,發如今當前做用域不存在變量b,而後往上一層(全局)去查找b,發現存在變量b,獲取b的值。code
在詞法分析階段,會確認在全局做用域裏有a,b這兩個變量,函數foo做用域裏有a這個變量對象
可是,有些方法能夠欺騙或者動態生成做用域。作用域
例如:eval、setTimeout、with等字符串
eval函數能夠理解爲在當前做用域插入一段代碼。編譯器
以下:it
var b = 2; function foo() { eval('var b=1') console.log(b); //1 } foo(); console.log(b); //2
在開始的詞法分析中,foo函數做用域並不存在變量b,然而在引擎執行代碼的時候,到eval函數執行,就強行在foo函數做用域中插入變量bio
setTimeoutconsole
定時器函數是一個異步函數,第一個參數中字符串的執行做用域是全局做用域,相似上面動態插入變量。
var b = 1; function foo() { setTimeout('var b =2', 0); setTimeout('console.log(b)', 0); //2 } foo(); console.log(b); //1
with
擴展一個語句的做用域鏈。
在一個對像是擴展屬性,若是屬性存在就修改屬性值,若是不存在就掛載在全局對象上,相似於在函數裏不用var聲明的變量都掛在window對象上。