1. JavaScript作用域
1.1 全局作用域
在代碼中任何地方都能訪問到的對象擁有全局作用域,一般來說以下幾種情形擁有全局作用域:
a) 最外層函數(shù)和在最外層函數(shù)外面定義的變量擁有全局作用域
b) 所有未定義直接賦值的變量自動聲明為擁有全局作用域双絮,如:
function test(){
a = 3; // a 具有全局作用域
var b = 4;
}
test();
console.log(a); //3
console.log(b); //Uncaught ReferenceError: b is not defined
c) 所有window對象的屬性擁有全局作用域
1.2 局部作用域
局部作用域一般只在固定的代碼片段內(nèi)可訪問到浴麻,最常見的如函數(shù)內(nèi)部。
2. JavaScript作用域鏈
????每個函數(shù)都有自己的執(zhí)行環(huán)境(execution context)囤攀,當(dāng)執(zhí)行流進(jìn)入一個環(huán)境時软免,函數(shù)的環(huán)境就會被推入一個環(huán)境棧中,在函數(shù)執(zhí)行之后焚挠,棧將其環(huán)境彈出膏萧,把控制權(quán)返回給之前的執(zhí)行環(huán)境。
????當(dāng)代碼在一個環(huán)境中執(zhí)行時,會創(chuàng)建變量對象的一個作用域鏈(scope chain)向抢。作用域鏈的用途认境,是保證對執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問。作用域鏈的前端挟鸠,始終都是當(dāng)前執(zhí)行的代碼所在環(huán)境的變量對象叉信。如果這個環(huán)境是函數(shù),則將其活動對象(activation object)作為變量對象艘希∨鹕恚活動對象在最開始時只包含一個變量,即 arguments 對象(這個對象在全局環(huán)境中是不存在的)覆享。作用域鏈中的下一個變量對象來自包含(外部)環(huán)境佳遂,而再下一個變量對象則來自下一個包含環(huán)境。這樣撒顿,一直延續(xù)到全局執(zhí)行環(huán)境丑罪;全局執(zhí)行環(huán)境的變量對象始終都是作用域鏈中的最后一個對象。
????標(biāo)識符解析是沿著作用域鏈一級一級地搜索標(biāo)識符的過程凤壁。搜索過程始終從作用域鏈的前端開始吩屹,然后逐級地向后回溯,直至找到標(biāo)識符為止(如果找不到標(biāo)識符拧抖,通常會導(dǎo)致錯誤發(fā)生)煤搜。
示例:
var a = 1
function fn1(){
function fn3(){
function fn2(){
console.log(a)
}
fn2()
var a = 4
}
var a = 2
return fn3
}
var fn = fn1()
fn()
上述代碼中,最終執(zhí)行的是fn2唧席,但是fn2中并沒有定義變量a擦盾,則從其上層作用域也就是fn3去尋找變量a的聲明,由于變量的聲明前置淌哟,但是賦值不會前置迹卢,可以在fn3中找到其局部變量a的聲明,但是未被賦值所以值為undefined绞绒,所以在執(zhí)行fn2時會輸出結(jié)果undefined婶希。