摘要:經(jīng)典面試題變量提升執(zhí)行環(huán)境作用域鏈今天記錄一個(gè)的經(jīng)典面試題,該編程題涉及到了的變量提升執(zhí)行環(huán)境作用域鏈問題。這樣,一致延續(xù)到全局執(zhí)行環(huán)境全局執(zhí)行環(huán)境的變量對(duì)象始終都是作用域鏈中的最后一個(gè)對(duì)象。
js經(jīng)典面試題--變量提升、執(zhí)行環(huán)境、作用域鏈
今天記錄一個(gè)js的經(jīng)典面試題,該編程題涉及到了js的變量提升、執(zhí)行環(huán)境、作用域鏈問題。
1、變量提升
js沒有塊級(jí)作用域,使用var聲明的變量會(huì)自動(dòng)添加到最接近的環(huán)境中。在函數(shù)內(nèi)部,最接近的環(huán)境就是函數(shù)的局部環(huán)境。如果初始化變量時(shí)沒有使用var變量,該變量會(huì)自動(dòng)被添加到全局環(huán)境。下面兩幅圖是等價(jià)的,結(jié)果都是控制臺(tái)打印出1 2 3 4 5
2、 執(zhí)行環(huán)境
每個(gè)函數(shù)都有自己的執(zhí)行環(huán)境。當(dāng)執(zhí)行流進(jìn)入一個(gè)函數(shù)時(shí)(即調(diào)用該函數(shù)),函數(shù)的環(huán)境就會(huì)被推入一個(gè)環(huán)境棧中。而在函數(shù)執(zhí)行之后,將其環(huán)境彈出棧,把控制權(quán)返回給之前的執(zhí)行環(huán)境。全局執(zhí)行環(huán)境是最外圍的一個(gè)執(zhí)行環(huán)境。全局執(zhí)行環(huán)境被認(rèn)為是window對(duì)象,全局執(zhí)行環(huán)境直到應(yīng)用程序退出--例如關(guān)閉網(wǎng)頁或?yàn)g覽器---時(shí)才會(huì)被銷毀。
function a(){ //執(zhí)行a功能代碼 } a(); //函數(shù)a的環(huán)境被推入一個(gè)環(huán)境棧中。 function b(){ //執(zhí)行b功能代碼 var c=function(){ //執(zhí)行c功能代碼 function d(){ //執(zhí)行d功能代碼 } retrun d(); } return c(); } b(); //函數(shù)b、c、d依次被推入一個(gè)環(huán)境棧中,當(dāng)調(diào)用b()函數(shù)時(shí),其依次被彈出
其執(zhí)行的具體流程如下圖所示:
3、作用域鏈
當(dāng)代碼在一個(gè)環(huán)境中執(zhí)行時(shí),會(huì)創(chuàng)建變量對(duì)象的一個(gè)作用域鏈。作用域鏈的用途,是保證對(duì)執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問。作用域鏈的前端,始終都是當(dāng)前執(zhí)行的代碼所在環(huán)境的變量對(duì)象。作用域鏈中的下一個(gè)變量對(duì)象來自包含(外部)環(huán)境,而再下一個(gè)變量對(duì)象則來自下一個(gè)包含環(huán)境。這樣,一致延續(xù)到全局執(zhí)行環(huán)境;全局執(zhí)行環(huán)境的變量對(duì)象始終都是作用域鏈中的最后一個(gè)對(duì)象。
var a=1; function b(){ //執(zhí)行b功能代碼 var bVar=1; var c=function(){ //執(zhí)行c功能代碼 var cVar=2; function d(){ //執(zhí)行d功能代碼 var dVar=3; cVar=3; } retrun d(); } return c(); } b();
以上代碼共涉及4個(gè)執(zhí)行環(huán)境:全局環(huán)境,b()的局部環(huán)境、c()的局部環(huán)境、d()的局部環(huán)境。全局環(huán)境有一個(gè)變量a和一個(gè)函數(shù)b()。b()的局部環(huán)境中有一個(gè)變量bVar和一個(gè)函數(shù)c.....依次。位于最里邊的函數(shù)可以訪問外部環(huán)境的所有變量和函數(shù),因?yàn)橥獠凯h(huán)境是它的父執(zhí)行環(huán)境??偨Y(jié):內(nèi)部環(huán)境可以通過作用域鏈訪問所有的外部環(huán)境,但外部環(huán)境無法訪問到內(nèi)部環(huán)境中的任何變量和函數(shù)。這些環(huán)境之間的聯(lián)系是線性、有次序的。每個(gè)環(huán)境都可以向上搜索作用域鏈,以查詢變量和函數(shù)名(服從就近原則);但任何環(huán)境都不能通過向下搜索作用域而進(jìn)入另一個(gè)執(zhí)行環(huán)境。
通過上面介紹執(zhí)行環(huán)境與作用域的兩幅圖可以看出,瀏覽器在執(zhí)行js時(shí),首先會(huì)將window對(duì)象(全局執(zhí)行環(huán)境)壓入環(huán)境棧,每次執(zhí)行一個(gè)函數(shù)時(shí),被調(diào)用的函數(shù)(按照調(diào)用的先后順序)依次壓入環(huán)境棧中。而壓入棧中的環(huán)境類似于容器,往棧底方向的容器包含了上面的容器。容器中存放的是自己的變量和函數(shù)以及上面的容器。我們可以把容器的玻璃的材質(zhì)想象為車窗戶(可以從里邊看到外面,但是無法從外面看到里邊),當(dāng)在某個(gè)環(huán)境(容器)中執(zhí)行代碼塊時(shí),就好比我們站在當(dāng)前容器里,此時(shí)我們可以看到外部容器(父級(jí)環(huán)境)的變量和函數(shù),但卻看不到內(nèi)部容器的任何東西,這就是作用域鏈。
下面進(jìn)入正題,說下我對(duì)該面試題的理解
1 var foo = {n:1}; 2 (function (foo) { 3 console.log(foo.n); 4 foo.n=3; 5 var foo = {n:2}; 6 console.log(foo.n); 7 })(foo); 8 console.log(foo.n);
上面的代碼其實(shí)可以寫成這樣:
1 var foo = {n:1}; 2 (function (foo) { 3 var foo; 4 console.log(foo.n); 5 foo.n=3; 6 var foo = {n:2}; 7 console.log(foo.n); 8 })(foo); 9 console.log(foo.n);
1、聲明一個(gè)變量,為引用類型
2和8、聲明一個(gè)匿名函數(shù),并立即執(zhí)行,傳遞的參數(shù)是第1行中的foo。將一個(gè)對(duì)象類型賦值給一個(gè)新的變量,由于對(duì)象是引用類型,實(shí)質(zhì)上是指將對(duì)象的地址賦值給該變量(也就是說這兩個(gè)變量指向同一個(gè)地址空間),因此改變新的變量中的屬性值或方法,對(duì)應(yīng)的原來對(duì)象的值也會(huì)改變。
3、原題中的第5行,由于存在變量提升,因此會(huì)在函數(shù)開始就聲明,此時(shí)為undefined;然而由于一個(gè)變量的聲明優(yōu)先級(jí)低于形參,所以這行沒有任何效果
4、打印形參的foo.n,打印1
5、改變第1行變量foo的屬性n的值為3;
6、重新聲明并定義了一個(gè)變量,開辟了新的內(nèi)存空間,n為2
7、由于js中的代碼是自上而下執(zhí)行,所以此時(shí)輸出2
9、上面的函數(shù)調(diào)用結(jié)束后,局部變量被銷毀,而之前的內(nèi)存空間值已經(jīng)變?yōu)?,所以輸出3
所以最終的結(jié)果為:1 2 3
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/94349.html
摘要:本篇收錄了一些面試中經(jīng)常會(huì)遇到的經(jīng)典面試題,并且都給出了我在網(wǎng)上收集的答案。網(wǎng)頁的行為層負(fù)責(zé)回答內(nèi)容應(yīng)該如何對(duì)事件做出反應(yīng)這一問題。 本篇收錄了一些面試中經(jīng)常會(huì)遇到的經(jīng)典面試題,并且都給出了我在網(wǎng)上收集的答案。眼看新的一年馬上就要開始了,相信很多的前端開發(fā)者會(huì)有一些跳槽的悸動(dòng),通過對(duì)本篇知識(shí)的整理以及經(jīng)驗(yàn)的總結(jié),希望能幫到更多的前端面試者。(如有錯(cuò)誤或更好的答案,歡迎指正,水平有限,望...
摘要:本篇收錄了一些面試中經(jīng)常會(huì)遇到的經(jīng)典面試題,并且都給出了我在網(wǎng)上收集的答案。網(wǎng)頁的行為層負(fù)責(zé)回答內(nèi)容應(yīng)該如何對(duì)事件做出反應(yīng)這一問題。 本篇收錄了一些面試中經(jīng)常會(huì)遇到的經(jīng)典面試題,并且都給出了我在網(wǎng)上收集的答案。眼看新的一年馬上就要開始了,相信很多的前端開發(fā)者會(huì)有一些跳槽的悸動(dòng),通過對(duì)本篇知識(shí)的整理以及經(jīng)驗(yàn)的總結(jié),希望能幫到更多的前端面試者。(如有錯(cuò)誤或更好的答案,歡迎指正,水平有限,望...
摘要:本篇收錄了一些面試中經(jīng)常會(huì)遇到的經(jīng)典面試題,并且都給出了我在網(wǎng)上收集的答案。網(wǎng)頁的行為層負(fù)責(zé)回答內(nèi)容應(yīng)該如何對(duì)事件做出反應(yīng)這一問題。 本篇收錄了一些面試中經(jīng)常會(huì)遇到的經(jīng)典面試題,并且都給出了我在網(wǎng)上收集的答案。眼看新的一年馬上就要開始了,相信很多的前端開發(fā)者會(huì)有一些跳槽的悸動(dòng),通過對(duì)本篇知識(shí)的整理以及經(jīng)驗(yàn)的總結(jié),希望能幫到更多的前端面試者。(如有錯(cuò)誤或更好的答案,歡迎指正,水平有限,望...
摘要:引言滿滿的干貨,面試必系列,參考大量資料,并集合自己的理解以及相關(guān)的面試題,對(duì)核心知識(shí)點(diǎn)中的作用域閉包上下文進(jìn)行了梳理。如果在小區(qū)這個(gè)作用域找到了張老師,我就會(huì)在張老師的輔導(dǎo)下學(xué)鋼琴我張老師房間鋼琴構(gòu)成了學(xué)琴的上下文環(huán)境。 showImg(https://segmentfault.com/img/bVbo4hv?w=1800&h=1000); 引言 滿滿的干貨,面試必bei系列,參考大...
閱讀 994·2021-11-23 09:51
閱讀 3486·2021-11-22 12:04
閱讀 2727·2021-11-11 16:55
閱讀 2955·2019-08-30 15:55
閱讀 3238·2019-08-29 14:22
閱讀 3361·2019-08-28 18:06
閱讀 1253·2019-08-26 18:36
閱讀 2138·2019-08-26 12:08