javascript篇-----執行環境和範圍

來源:互聯網
上載者:User

標籤:.com   ges   方法   red   必須   它的   pre   沒有   語言   

  執行環境是javascript中最為重要的一個概念。執行環境定義了變數或函數有權訪問的其他資料,決定了它們各自的行為。每個執行環境都有一個與之關聯的變數對象,環境中定義的所有變數和函數都儲存在這個對象中。

  全域執行性環境是最外圍的一個執行環境,根據ECMAScript實現所在的宿主環境不同,表示執行環境的對象也不一樣。在Web瀏覽器中,全域執行環境被認為是window對象,因為所有的全域變數和函數都是作為window對象的屬性和方法建立的。某個執行環境中的所有代碼執行完畢後,該環境被銷毀,儲存在其中的所有變數和函數定義也隨之銷毀。

  每個函數都有自己的執行環境。當執行流進入一個函數時,函數的環境就會被推入一個環境棧中。而在函數執行之後,棧將其環境彈出,把控制權返回給之前的執行環境。ECMAScript程式中的執行流正是由這個方便的機制控制的。

  當代碼在一個環境中執行時,會建立變數對象的一個範圍鏈。範圍鏈的用途,是在保證對執行環境有權訪問的所有變數和函數都有序訪問。範圍鏈的前端,始終都是當前執行的代碼所在環境的變數對象。如果這個環境是函數,則將其使用中的物件作為變數對象。使用中的物件在最開始時只包含一個變數,即arguments對象。範圍鏈中的下一個變數對象來自包含環境,而在下一個變數對象則來自下一個包含環境。這樣,一直延續到全域執行環境。全域執行環境的變數對象始終都是範圍鏈中的最後一個對象。

  標識符解析是沿著範圍鏈一級一級地搜尋標識符的過程。搜尋過程始終從範圍鏈的前端開始,然後逐級的向後回溯,直至找到標識符為止。

 1 { 2   var color = ‘blue‘; 3   function changeColor () { 4     var anotherColor = ‘red‘; 5     function swapColors () { 6       var tempColor = anotherColor; 7       anotherColor = color; 8       color = tempColor; 9       // swapColors()的局部環境,這裡可以訪問color,anotherColor和tempColor10     }11     // changeColor()的局部環境,這裡可以訪問color和anotherColor,但不能訪問tempColor12     swapColors();13   }14   // 全域環境window,這裡只能訪問color15   changeColor();16 }

  上面的代碼共涉及3個執行環境:全域環境、changeColor()局部環境和swapColors()的局部環境。全域環境中有一個變數color和一個函數changeColor()。changeColor()的局部環境中有一個名為anotherColor的變數和一個名為swapColors()的函數,但它也可以訪問全域環境中的變數color。swapColors()的局部環境中有一個變數tempColor,該變數只能在這個環境中訪問到。無論全域環境還是changeColor()的局部環境都無權訪問tempColor。然而,在swapColors()內部則可以訪問其他兩個環境中的所有變數,因為那兩個環境是它的父執行環境。下面的圖展現了上面的代碼的範圍鏈結構。

延長範圍鏈

  下列語句可以在範圍鏈的前端臨時增加一個變數對象,該變數對象的會在代碼執行後被移除,

    • try-catch語句的catch塊;
    • with語句;

  這兩個語句都會在範圍的前端添加一個變數對象。對於with語句來說,會將制定的對象添加到範圍鏈中。對catch語句來說,會建立一個新的變數對象,其中包含的是被拋出的錯誤對象的聲明。

1 {2   function buildUrl () {3     var qs = ‘?debug=true‘;4     with (location) {5       var url = href + qs;6     }7     return url;8   }9 }

  上面的代碼中,with語句接受的是location對象,因此其變數對象中就包含了location對象的所有屬性和方法,而這個變數對象被添加到了範圍鏈的前端。buildUrl()函數中定義了一個變數qs。當在with語句中引用變數href時(實際引用的是location.href),可以在當前執行環境的變數對象中找到。當引用變數qs時,引用的則是在buildUrl()中定義的那個變數,而該變數位於函數環境的變數對象中。至於with語句內部,則定義了一個名為url的變數,因而url就成了函數執行環境的一部分,所以可以作為函數的值被返回。

沒有塊級範圍

  在其他類C的語言中,由花括弧封閉的代碼塊都有自己的範圍,即塊級範圍。對於有塊級範圍的語言來說,塊內的代碼會在塊執行完畢之後被銷毀。但對於ECMAScript來說,並沒有塊級範圍,只有函數範圍,只有在函數塊執行完畢之後才會銷毀變數對象。

 聲明變數

  使用var聲明的變數會自動被添加到最接近的環境中。在函數內部,最接近的環境就是函數的局部環境。在with語句中,最接近的環境是函數環境。如果初始設定變數時沒有使用var聲明,該變數會自動的被添加到全域環境。

 1 { 2   function add (num1, num2) { 3     var sum = num1 + num2; 4     return sum; 5   } 6   var result = add(10, 20);// 30 7   //console.log(sum);// 會報錯,sum定義在add()的局部範圍中,全域範圍中訪問不到 8   function add1 (num1, num2) { 9     sum1 = num1 + num2;// 未使用var聲明變數,會被添加到全域範圍中10     return sum1;11   }12   var result1 = add1(10, 30);// 4013   console.log(sum1);// 40,能夠訪問到被添加到全域範圍中的sum114 }
查詢標識符

  當在某個環境中為了讀取或寫入而引用一個標識符時,必須通過搜尋來確定該標識符實際代表什麼。搜尋過程從範圍鏈的前端開始,向上逐級查詢與給定名字匹配的標識符。如果在局部環境中找到了該標識符,搜尋過程停止,變數就緒。如果在局部環境中沒有找到該變數名,則繼續沿範圍鏈向上搜尋。搜尋過程將一直追溯到全域環境的變數對象。如果在全域環境中也沒有找到這個標識符,則意味著該變數尚未聲明。

  在這個搜尋過程中,如果存在一個局部的變數的定義,則搜尋自動停止,不再進入另一個變數對象。換句話說,如果局部環境中存在同名標識符,就不會使用位於父環境中的標識符。

1 {2   var color = ‘blue‘;3   function getColor () {4     var color = ‘red‘;5     return color;6   }7   console.log(getColor());// "red"8 }

   在上面的代碼中,getColor()函數中聲明了一個名為color的局部變數。調用函數時,該變數就會被聲明。而當函數中的第二行代碼執行時,意味著必須找到並返回變數color的值。搜尋過程首先從局部環境中開始,而且在這裡發現了一個名為color的變數,其值為“red”。因為變數已經找到了,所以搜尋即刻停止,return語句就使用這個局部變數,並為函數會返回“red”。也就是說,任何位於局部變數color的聲明之後的代碼,如果不使用window.color都無法訪問全域color變數。展現整個的搜尋步驟。

 

javascript篇-----執行環境和範圍

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.