轉(zhuǎn)載地址:
http://blog.csdn.net/itzhengmaolin/article/details/54565201
作用域:在一定的范圍內(nèi)多艇,對(duì)其進(jìn)行讀洁墙、寫操作“js解析器”執(zhí)行的過(guò)程至少2步:1实蔽、"找一些東西":比如 var 别垮、function涯贞、參數(shù)2庭瑰、逐行解讀代碼例:
alert(a);var a=1;function fn1(){ alert(2);}
解析過(guò)程:
1星持、JS的預(yù)解析過(guò)程 原則:遇到重名的:只留一個(gè)(變量和函數(shù)重名了,就只留下函數(shù)弹灭。無(wú)論變量在上還是函數(shù)在上督暂,與上下是沒(méi)關(guān)系的,跟有值沒(méi)值有關(guān)系穷吮。因?yàn)樽兞?undefined逻翁,函數(shù)=整個(gè)函數(shù)塊,相比之下有具體值的級(jí)別更大)
找到var關(guān)鍵字捡鱼,然后定義其變量名等于undefined八回,不會(huì)管后面的值(在"JS解析器"執(zhí)行的過(guò)程中,所有的變量都等于未定義) 如:a=undefined
找到function關(guān)鍵字驾诈,然后用其函數(shù)名等于其整個(gè)函數(shù)塊缠诅。(所有的函數(shù),在正式運(yùn)行代碼之前乍迄,都提前賦了一個(gè)值管引,這個(gè)值為整個(gè)函數(shù)塊) 如:fn1=function fn1(){alert(2);}
2、逐行解讀代碼過(guò)程: 表達(dá)式可以修改"預(yù)解析"的值闯两。函數(shù)的聲明不屬于表達(dá)式汉匙,改變不了什么東西這個(gè)過(guò)程遵循"從上往下,從左往右"的順序執(zhí)行生蚁。當(dāng)執(zhí)行一句完畢后噩翠,到倉(cāng)庫(kù)中查找是否有這個(gè)"東西"(變量、函數(shù)等)邦投。如果有則彈出其一開(kāi)始在倉(cāng)庫(kù)的值(使用alert方法)遇到表達(dá)式(=+ - * / % ++ -- ! 參數(shù)……等即能改變值的東西)簡(jiǎn)單來(lái)說(shuō)伤锚,找var 、function志衣、參數(shù)屯援,并將變量賦值為undefined、函數(shù)名=整個(gè)函數(shù)念脯,然后將他們存儲(chǔ)在倉(cāng)庫(kù)中狞洋,在進(jìn)行逐行解讀代碼的時(shí)候,在倉(cāng)庫(kù)中提取或修改
練習(xí):
解析過(guò)程
1绿店、找關(guān)鍵字(var吉懊、function庐橙、參數(shù))找到37行的"var a",執(zhí)行過(guò)程:a=undefined找到39行的"function a(){alert(2);}",執(zhí)行過(guò)程:a=function a(){alert(2);}因?yàn)閭}(cāng)庫(kù)里有重名的a,所以要比較優(yōu)先級(jí),值為函數(shù)的大于值為未定義借嗽,所以執(zhí)行過(guò)程為a=function a(){alert(2);}找到41行的"var a ",執(zhí)行過(guò)程:a=undefined因?yàn)閭}(cāng)庫(kù)里有重名的a,所以要比較優(yōu)先級(jí)态鳖,值為函數(shù)的大于值為未定義,所以執(zhí)行過(guò)程為a=function a(){alert(2);}找到43行的"function (){alert(4);}",執(zhí)行過(guò)程:a=function (){alert(4);}因?yàn)閭}(cāng)庫(kù)里有重名的a,所以要比較優(yōu)先級(jí)恶导,值同為函數(shù)則比較先后浆竭,后面的覆蓋前面的,所以執(zhí)行過(guò)程為a=function a(){alert(4);}2惨寿、逐行解析:從上往下邦泄,從左到右依次執(zhí)行代碼。從36行開(kāi)始裂垦,a的一開(kāi)始值為function a(){alert(4);}執(zhí)行37行時(shí)顺囊,修改倉(cāng)庫(kù)中a的值,則變?yōu)?執(zhí)行39行時(shí)缸废,并不影響a的值,所以a的值還是1后面亦是如此
一個(gè)頁(yè)面兩個(gè)script標(biāo)簽驶社,瀏覽器遇到script標(biāo)簽會(huì)用"js解析器"來(lái)解析企量,只有解析完第一個(gè)script標(biāo)簽的內(nèi)容后在執(zhí)行下一個(gè)script標(biāo)簽內(nèi)的內(nèi)容,所以下面alert(a); 會(huì)報(bào)錯(cuò) a is no defined亡电。
這就是當(dāng)引用別人寫的jQuery庫(kù)時(shí)届巩,在對(duì)其修改
var a = 1;
function fn1()
{
alert(a); //undefined var a = 2;
}
fn1();
alert(a);
//1解析過(guò)程:
1、預(yù)解析:a=undefined;fn1=function fn1(){ alert(a); var a = 2;}
2份乒、逐行解析;a=1遇到函數(shù)調(diào)用fn1() --函數(shù)也是一個(gè)局部的域恕汇,只要是一個(gè)域就會(huì)發(fā)生預(yù)解析和逐行解讀代碼。相當(dāng)于其有一個(gè)小的倉(cāng)庫(kù)或辖●ⅲ可以理解為1個(gè)大倉(cāng)庫(kù)包含著1個(gè)小倉(cāng)庫(kù),大倉(cāng)庫(kù)里的a和小倉(cāng)庫(kù)里的a是不同的世界颂暇,互不影響缺谴。函數(shù)調(diào)用屬于表達(dá)式 函數(shù)里的預(yù)解析: a=undefined; //這里的a是局部的,外面的是全局的耳鸯,兩者沒(méi)關(guān)系 函數(shù)里的逐行解析: 執(zhí)行函數(shù)里的alert(a); 先找局部倉(cāng)庫(kù)里的a湿蛔,所以彈出undefined 在執(zhí)行函數(shù)里的var a=2; 所以局部里的a=2县爬,并沒(méi)有影響全局中的a=1 函數(shù)執(zhí)行完畢后會(huì)有垃圾回收機(jī)制等
函數(shù)調(diào)用完畢后阳啥,繼續(xù)全局的逐行解析
var a = 1;function fn1(){alert(a); // 1a = 2;
//注意這里沒(méi)用var聲明}fn1();alert(a); // 2函數(shù)里的預(yù)解析過(guò)程為空,執(zhí)行函數(shù)里的逐行解析代碼:當(dāng)執(zhí)行到alert(a);沒(méi)找到a财喳,會(huì)順著函數(shù)的作用域跳到上一級(jí)(從子級(jí)作用域返回到父級(jí)作用域的過(guò)程叫作用域鏈察迟,由里到外找)。執(zhí)行到"a=2"時(shí),發(fā)現(xiàn)小倉(cāng)庫(kù)里沒(méi)有a卷拘,則由里到外找喊废,找到其父級(jí)有a,則修改a的值為2
所以栗弟,加var與不加var的區(qū)別體現(xiàn)出來(lái)了污筷。不加var,會(huì)修改全局變量的值
var a = 1;function fn1(a){alert(a); // undefineda = 2;}fn1();alert(a); // 1
參數(shù)本質(zhì)就是一個(gè)局部變量乍赫。跟上面的其中一種情況(如下)很類似函數(shù)預(yù)解析時(shí)沒(méi)有發(fā)現(xiàn)var瓣蛀、function ,卻發(fā)現(xiàn)了參數(shù)雷厂,所以a=undefined惋增。然后逐行解讀代碼,當(dāng)讀到"alert(a);"改鲫,執(zhí)行結(jié)果為undefined當(dāng)讀到"a=2;",它會(huì)就近找小倉(cāng)庫(kù)里有沒(méi)有a诈皿,執(zhí)行結(jié)果為a=2,全局的a還是1不影響