第一次寫博,還蠻激動。。。 看到了三題經典題型,經老師講解後,對此類題目有了更深刻的認識 就我目前的認識對此題進行總結。如有錯誤,敬請指正 首先,我們先明確一下JS引擎的工作步驟: js引擎工作分為兩步: 1.將這個js中的變數和函數聲明保存到當前(註意,是當前)執行環境的變數對象中 2.再逐行解析 ...
第一次寫博,還蠻激動。。。
看到了三題經典題型,經老師講解後,對此類題目有了更深刻的認識
就我目前的認識對此題進行總結。如有錯誤,敬請指正
首先,我們先明確一下JS引擎的工作步驟:
js引擎工作分為兩步:
1.將這個js中的變數和函數聲明保存到當前(註意,是當前)執行環境的變數對象中
2.再逐行解析執行js。當看到一個函數或一個變數時,js引擎就會去查詢 這個函數或變數是在哪裡定義的
查詢的方式有兩種:
a.按作用域鏈查找:先在當前執行環境查詢這個變數或程式,如果沒有,就到父執行環境 中查找,還沒有就繼續向上查找,一直到window
b.從對象中查找:如果一個函數是用對象來調用的,就可以從這個對象中查找,如果 在執行環境中沒有找到,會報錯,如果在對象中沒有找到,會返回undefined
照我個人的理解:每一個函數都是一個獨立的執行環境,在每一個執行環境中,都有兩個工作步驟,也就是1和2,下麵就題目分析
第一題:
1 var a = 10; 2 function test(){ 3 a = 100; 4 alert(a); 5 alert(this.a); 6 var a; 7 alert(a); 8 } 9 test();
答案:100 10 100
就代碼解析:函數的工作域是window,首先進行第1步:將變數和函數聲明保存到當前執行環境的變數對象中,個人對此句話的理解是:引擎工作的第一步是將變數和函數的聲明提前,相當於:
var a; var test;
之後開始第2步:逐行解析執行js,首先將10賦值給a,然後跳過沒有自執行的test函數,開始第9句,第9句是一句對test()函數調用,執行環境要註意是window,因此,test函數中的this指向的必然是window。進入test函數內部,與開始時的步驟相同,第一步,將變數及函數聲明提前至解析函數之前,即:
var a;
之後開始對函數內代碼逐條執行,首先將100賦值給a,則此時,a 結果為100;而this指的是調用此函數的對象,由第9句,由上述的分析知this指的是window,因此this.a 指的是window中的變數a,其值為10,因此第5句結果為10;第六句在test解析時就被提前了,所以可直接跳到第7句,此時的a指向的還是函數內部的變數a,因此結果為100。
第二題:
1 var a = 100; 2 function test(){ 3 alert(a); 4 var a = 10; 5 alert(a); 6 } 7 test();
答案:undefined 10
就代碼解析:函數的工作域是window,依舊是進行第1步:
var a; var test;
之後進行逐行解析,第1行將100賦值給a,第7行調用此函數,在被調用的函數test()內,首先有
var a;
第2步,逐行解析,a在其執行環境中已經被定義,所以不會有是全局變數的可能,但因第一步只是把變數聲明提前,而非將其賦值,因此在第3句中,a是一個聲明但未初始化的值,因此其結果為undefined。第4句將10賦值給a,因此第5句結果為10。
第三題:
1 var a = 100; 2 function test(){ 3 alert(a); 4 a = 10; 5 alert(a); 6 } 7 test(); 8 alert(a);
答案:100 10 10
就代碼解析:函數的工作域是window,依舊是進行第1步:
var a; var test;
逐行解析:第1行將100賦值給a,第7行調用此函數,在被調用的函數test()內,第一遍並沒有變數聲明或函數聲明,因此進入第2步,依舊是逐行解析,第3行,a在其執行環境中並無聲明,由開頭介紹的js引擎的第2步a中介紹,先在當前執行環境查詢這個變數或程式,如果沒有,就到父執行環境 中查找,還沒有就繼續向上查找,一直到window。因此a在test中並非局部變數,而是window的全局變數,即a的結果是100;第4行中,全局變數a的值修改為10,因此第5行結果為10;在函數結束後,全局變數a的值已經被修改為10,因此第8行結果為10。