JavaScript函數之範圍 / 作用鏈域 / 預解析

來源:互聯網
上載者:User

標籤:

關於範圍和作用鏈域的問題,很多文章講的都很詳細,本文屬於摘錄自己覺得對自己有價值的部分,留由後用,僅供參考,需要查看詳細資料請點擊我給出的原文連結查看原檔案

做一個有愛的搬運工~~

-------------------------------------------------------------------------------------------------------------------------------------------

範圍

js中範圍只有一種,就是函數範圍,除此之外,還存在一種範圍叫塊範圍,但在此之前,想先說一下什麼叫做塊

  

  在JAVA或者C中(因為我只學過這兩種語言),塊就是寫在{}中的語句,一般看作一條語句執行,

  塊範圍(JS中不存在塊範圍的概念)

  在塊中的語句對塊外是封閉的,在JAVA和C中都有這樣的特性

  例如

//JAVA 代碼public class Block {    public static void main(String[] args) {        if(true){            int i = 9;        }        System.out.println(i);//代碼報錯    }}//以上的代碼編譯時間會報錯,強制編譯並執行時會拋出以下的錯誤://Exception in thread "main" java.lang.Error: Unresolved //compilation problem: i cannot be resolved to a variable

  所以,JAVA是有塊範圍的概念的,同樣的代碼,放在JS中時

//JavaScript代碼function fun(){        if(true){                var i = 9;        }        return i;}fun();//輸出 9

  這就說明, 在if語句中聲明的變數在if語句之後被保留在記憶體中了,並沒有銷毀.

  需要特別說明的是:JS中,在函數中用var定義的變數是局部變數,不用var定義的變數會預設作為全域變數使用

function f1(){        var n=9;        m = 10;  }f1();console.log(n);//不會輸出結果,報錯誤:ReferenceError: n is not defined, 意思是該變數未定義console.log(m);//輸出10

  關於這個說法,在很多文章中都有提及,比如 Javascript中模仿塊級範圍  : 其中對JS中範圍的解釋說:使用var關鍵字聲明變數時,這個變數會自動添加到距離最近的可用環境中。對於函數而言,這個最近的環境就是函數的局部環境。如果變數在未經聲明的情況下被初始化,則該變數會被自動添加到全域環境。

 

在JS中實現塊範圍的使用效果

同樣在  Javascript中模仿塊級範圍 這篇文章中,利用匿名函數來實現塊範圍的功能

 

(function(){    //塊級範圍})();
//來自原文的話: 這種技術常在全域範圍中用在函數外部,來限制向全域範圍中添加過多的變數和函數。當然,只要我們臨時需要一些變數,都可以使用塊級範圍(私人範圍)。當匿名函數執行完畢,其範圍鏈立即銷毀,從而可以減少閉包佔用資源問題。

  在這裡再貼一個也比較好的說明範圍知識的文章 js範圍問題一步步透徹理解

  這篇文章中,有這樣一個例子(這個細節是我之前並沒有注意過的>>細節指數:★★★★)

function fun(){        var a = b = 10;}console.log(a);//ReferenceError: a is not definedconsole.log(b);//輸出: 10/* *原文的話:  var a = b = 10; 這種寫法在函數內: b其實是全域變數,a當然是局部變數 */

  所以我自己給出了下面的例子

function fun(){        var a = 10, b = 10;}console.log(a);//ReferenceError: a is not definedconsole.log(b);//ReferenceError: b is not defined/* *a是局部變數 *b是局部變數 *我們可以很清楚的知道, var a = 10, b = 10; 這種寫法在函數內是定義局部變數的有效方法, */

-----------------------------------------------------------------------------------------------------------------------

作用鏈域

  預解析(在說作用鏈域之前,我想先說一個問題---預解析,先給出引用的文章地址, 方便回溯)

  解釋一下啥叫預解析(自己起的名),希望給一些初學js的提供些協助

  說法:js引擎讀取一段js代碼,首先預解析(這個名字我起的),就是逐行讀取js代碼,尋找全域變數和全域函數,遇到全域變數,把變數的值變為undefind,存在記憶體中,遇到全域函數,直接存在記憶體中,這個過程如果發現語法錯誤,預解析終止。

  當預解析完成後,js引擎在從第一行開始逐行運行js代碼。

  js的預解析

  說法:js的預解析是在程式進入一個新的環境時,把該環境裡的變數或函數預解析到它們能調用的環境中。即每一次預解析的單位是一個執行環境。

  轉:javascript(js)預解析原理

  說法:函數預解析

  1、javascript在執行前會進行類似“預解析”的操作:首先會建立一個在當前執行環境下的使用中的物件,並將那些用var 聲明的變數、定義的函數設定為使用中的物件的屬性,但是此時這些變數的賦值都是undefined。

  2、在javascript解釋執行階段,遇到變數需要解析時,會首先從當前執行環境的使用中的物件中尋找,如果沒有找到‍而且該執行環境的擁有者有prototype屬性時則會從prototype鏈中尋找,否則將會按照範圍鏈尋找。遇到var a = …這樣的語句時會給相應的變數進行賦值(注意:變數的賦值是在解釋執行階段完成的,如果在這之前使用變數,它的值會是undefined)。

 

//預先處理的例子console.log(a);//輸出: undefinedconsole.log(b);//輸出: undefinedconsole.log(c);//輸出: function c(){return "C";}var a = "A";var b = function(){return "B"; }function c(){return "C";}

//在文法分析階段,a儲存用var進行顯示聲明的局部變數,並且置預設值為undefined,這裡就是上述代碼中"console.log(a)"輸出為undefined的原因,由於代碼在文法分析階段就已經保留了標記符a,在指派陳述式"var a = "A"; "執行之前a的值都是undefined,因此在"console.log(a)"的時候就顯示為undefined了。(修改引用自:(轉載)淺談JavaScript的閉包和範圍鏈)

 

 

  至此,如果預解析的概念有所瞭解了(其實我還沒有完全理解,疑問就是:上例中的b和c的輸出結果為什麼不一樣???如果有人理解,可以評論告訴我,不勝感激),就可以來說說作用鏈域的事兒了.

  作用鏈域

  看看這篇文章:  (轉載)淺談JavaScript的閉包和範圍鏈(這篇文章講了很多機制性的東西,個人覺得比較好!!!)

  原文:範圍鏈(scope chain)就是由範圍組成的鏈,是一個類似鏈狀的資料結構。範圍就是對上下文環境的資料描述。閉包和範圍鏈是緊密關係的,函數執行個體執行時的閉包是構成範圍鏈的基本元素。JavaScript代碼在執行前會進行文法分析,在文法分析階段,會記錄全域環境中的變數聲明和函數定義,建構函式的調用對象(Call Oject、Activation Object、Activate Object、使用中的物件,不同稱呼罷了)和在全域環境下的範圍鏈。

  [  關於閉包的內容我會在下一篇文章  JavaScript函數之閉包  中具體來說  ]

  至於作用鏈域的其他知識點,我感覺沒有辦法總結的比文章(轉載)淺談JavaScript的閉包和範圍鏈要好,所以,不多說,看原文!

--------------------------------------------------------------------------------------------------------------------------

參考文章:

Javascript中模仿塊級範圍

js範圍問題一步步透徹理解

解釋一下啥叫預解析(自己起的名),希望給一些初學js的提供些協助

js的預解析

轉:javascript(js)預解析原理

(轉載)淺談JavaScript的閉包和範圍鏈

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.