js做用域理解

學習筆記:(圖中水印來自同名微信訂閱號,現已更名爲‘碼上猿夢’)javascript

//javaScript做用域:html

    //首先聲明一點,js中沒有塊級做用域,java

        好比java中for循環中for(int i = 0; i < arr.length; i++){}中的變量i只能在for循環的大括號內部能訪問,c#

     //可是在js中,for(var i = 0; i < arr.length; i++){},i的做用域是包含了這個for循環的函數的做用域,或者是全局做用域.微信

 

1.全局做用域函數

(1).最外層函數和定義在最外層函數外面的變量具備全局做用域:性能

        (2).沒有使用var關鍵字聲明變量學習

上面的代碼等價於下面的代碼:(沒有使用var關鍵字聲明的a自動變爲全局變量)測試

//2.局部做用域this

//與全局做用域相反,局部做用域就是聲明定義在函數內部的變量或者函數,他們擁有局部做用域,也叫函數做用域,

//這些變量也叫局部變量,這些變量只能在聲明定義他們的函數裏面訪問,

 

        //做用域鏈:以前學過java, 目前在自學c#和javaScript, 學js才發如今js中真的是萬物皆對象: 在普通代碼中表現的比在java和c#中更加完全. C#中的委託將函數名做爲對象當成參數傳遞, java中也有這樣的 , 那就反射. js中全部的東西都是對象, 函數也是對象, 它具備屬性和方法, ( 在java中函數也能夠說是方法, 但在js中這樣說函數比較恰當,由於函數也是具備方法的. )

        //函數和其餘對象同樣, 擁有能夠經過代碼訪問的屬性和一系列僅供js引擎訪問的內部屬性, 其中有一個內部屬性就是做用域鏈 [[scope]] , 這個內部屬性包含了函數被建立時函數做用域中全部對象 ( 函數裏面的函數也是對象 ) 的集合, 這個集合被稱爲函數的做用域鏈, 它決定了哪些數據可以被這個函數訪問. 每一個函數都會有這樣一個做用域鏈, 這樣一來就會有不少個不一樣做用域鏈,

[[scope]] 裏面存放的只是一個地址, 也就是Scope chain的地址,[[scope]]指向了Scope chain,Scope chain是一個鏈表結構,裏面存放着各類函數做用域,其中也包括全局做用域,

        //程序尚未執行的時候,這個鏈表的最頂端存放的是全局做用域,好比這段代碼:

        當函數被建立的時候,它的做用域鏈就會填入一個全局對象,這個全局對象包含了全部的全局變量,(只列舉了部分變量)

以下圖:

//若是開始執行add函數,

var total = add(5, 10);

 

        //那麼這個鏈表的最頂端必定是當前正在執行的函數的函數做用域(是函數做用域,不是做用域鏈),全局做用域天然在第二層了(其實在這裏我在想,這裏的鏈表是否是棧,這點我沒有想明白,留一個疑問吧,之後再思考)

//補充一點:當執行流進入一個函數時,也就是一個函數要被執行時,會建立一個"運行時期上下文(execution context)"的執行環境,這也是一個內部對象, 這個運行時期上下文也是一個做用域鏈, 也是包含着該函數做用域中全部的對象, 運行時期上下文做用域鏈是由以前這個函數的做用域鏈初始化的, 而後js引擎又會去建立一個活動對象(Active Object),這個活動對象包含了函數運行期全部的局部變量,參數以及this等變量,

以下圖:

 

        //這個活動對象用於標識符的解析,也就是當你要使用一個變量時,活動對象會去它的做用域鏈中的一個個函數做用域去遍歷尋找該變量的標識符,若是找到了就使用這個標識符對應的變量,

若是沒有找到,那就向下遍歷另外一個函數做用域,直到找到爲止,可是若是一直遍歷到了全局做用域都沒有找到和該標識符的定義,那就好吧,我給你報錯.

(並且每一個標識符都要經歷這個遍歷尋找的過程,因此儘可能少使用全局變量,而應該多使用局部變量,有一個好的經驗法則就是:若是一個跨做用域的對象被使用了一次以上,那就把它存儲在局部做用域裏再使用,這樣也能減小代碼量,但最重要的是提升了程序的性能.好比document這個全局變量,)

 

以上代碼文字均手敲測試過,若有錯誤請指出,謝謝啦~~

歡迎關注同名微信訂閱號:碼上猿夢

筆記參考自夢想天空的博客,

博客地址:http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html

相關文章
相關標籤/搜索