成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript 作用域和作用域鏈學(xué)習(xí)

史占廣 / 1257人閱讀

摘要:作用域與作用域鏈每個函數(shù)都有自己的執(zhí)行環(huán)境。這是初步了解作用域,如想更深入了解作用域,請看下面鏈接作用域原理作用域鏈由一道題圖解的作用域或者看權(quán)威指南和高級程序設(shè)計

本文是我學(xué)習(xí)JavaScript作用域整理的筆記,如有不對,請多指出。

作用域

一個變量的作用域是程序源代碼中定義這個變量的區(qū)域。

而在ES5中只分為全局作用域和函數(shù)作用域,也就是說for,if,while等語句是不會創(chuàng)建作用域的。ES6(let,const)除外。

    //全局作用域
   var a = 123;
   function aa () {
       //局部作用域
       var b = 456;                            
   }
聲明提前

JavaScript函數(shù)里聲明的所有變量(但不涉及賦值)都被“提升”至函數(shù)體的頂部,在代碼開始運行之前。這個特性被稱為聲明提前。

    var a = "g";
    function f() {
      console.log(a); //輸出undefined
      var a = "l";
      console.log(a); //輸出"l"
    } 

由于函數(shù)作用域的特性,局部變量在整個函數(shù)體始終是有定義的,也就是說,函數(shù)體的局部變量覆蓋了同名全局變量。在函數(shù)體內(nèi),變量a被“提前”了,提前至函數(shù)體的頂部,所以第一次輸出的是undefined,那時候還沒賦值,但代碼執(zhí)行到var語句時候,局部變量才會被賦值。因此第二次輸出則是“l(fā)”。此代碼過程如下:

    var a = "g";
    function f() {
        var a; 
        console.log(a); //輸出undefined
        a = "l";
        console.log(a); //輸出"l"
   } 

因此一些程序員特意將變量聲明放在函數(shù)體的頂部,而不是將聲明靠近放在使用變量之處。

作用域鏈

先看一段簡單代碼,代碼如下:

var name = "wythe";
function one () {
    console.log(name); //wythe
    var firend = "zero";
}
one();
console.log(firend); //報錯

看到代碼可知,name是在全局作用域中聲明的全局變量,而firend則是在函數(shù)作用域中聲明的局部變量。在執(zhí)行時候你會發(fā)現(xiàn)函數(shù)作用域能夠訪問到在全局作用域中name這個變量,而全局作用域卻不能訪問到函數(shù)作用域的friend的變量,原因是作用域鏈!
作用域鏈的規(guī)則:
外部不能訪問內(nèi)部變量,內(nèi)部可以訪問外部變量
為什么會有這樣規(guī)則?因為是執(zhí)行環(huán)境所規(guī)定的。

執(zhí)行環(huán)境定義了變量或函數(shù)有權(quán)訪問其他數(shù)據(jù),決定了它們的行為。每個執(zhí)行環(huán)境都有一個與之關(guān)聯(lián)的變量對象(variable object),環(huán)境中定義的所有變量和函數(shù)都保存在這個對象中。
全局執(zhí)行環(huán)境是最外圍的一個執(zhí)行環(huán)境。在Web瀏覽器中,全局執(zhí)行環(huán)境被認為是window對象。某個執(zhí)行環(huán)境中所有所有代碼執(zhí)行完畢后,該環(huán)境被銷毀,保存在其中的所有的變量和函數(shù)定義也隨之銷毀。

補充說明:需要了解一些概念,變量對象(Variable Object)、活動對象(Activation Object)、函數(shù)的屬性[[scope]].

變量對象指的是變量對象(縮寫為VO)是一個與執(zhí)行上下文相關(guān)的特殊對象,它存儲著在上下文中聲明的內(nèi)容有:變量 (var, 變量聲明)、函數(shù)聲明和函數(shù)的形參。

執(zhí)行上下文(執(zhí)行環(huán)境):每次當控制器轉(zhuǎn)到ECMAScript可執(zhí)行代碼的時候,即會進入到一個執(zhí)行上下文。執(zhí)行上下文(簡稱-EC)是ECMA-262標準里的一個抽象概念,用于同可執(zhí)行代碼(executable code)概念進行區(qū)分。

活動對象指的是由函數(shù)的運行期上下文(代碼執(zhí)行前)創(chuàng)建,在運行時可變,初始時只有 arguments 屬性,通過變量的初始化,包含了局部變量、命名參數(shù)、 this 等

湯姆大叔深入理解JavaScript變量對象

函數(shù)屬性[[scope]]指的是函數(shù)對象都有一個內(nèi)部屬性 [[scope]],函數(shù)被創(chuàng)建后,函數(shù) [[scope]] 屬性會被創(chuàng)建此函數(shù)的作用域中可訪問的數(shù)據(jù)對象填充,是所有父變量對象的層級鏈。[[scope]] 在函數(shù)被創(chuàng)建時靜態(tài)存儲,永遠不會改變,直至銷毀。

作用域與作用域鏈

每個函數(shù)都有自己的執(zhí)行環(huán)境。當執(zhí)行流進入一個函數(shù)時,函數(shù)的環(huán)境就會被推入一個環(huán)境棧中。而在函數(shù)執(zhí)行之后,棧將環(huán)境彈出,把控制權(quán)返回之前的執(zhí)行環(huán)境。當代碼在一個環(huán)境執(zhí)行時候,會創(chuàng)建變量對象的一個作用域鏈(scope chain)。作用域的前端,始終都是當前執(zhí)行的代碼所在環(huán)境的變量對象。如何這個環(huán)境是函數(shù),則將其活動對象(activation object)作為變量對象?;顒訉ο笤谧铋_始只包含一個變量,即arguments對象(這個對象在全局環(huán)境是不存在)。作用域鏈中的下一個變量對象來自包含(外部)環(huán)境,而再下一個變量對象則來自下一個包含對象。這樣,一直延續(xù)到全局執(zhí)行環(huán)境;全局執(zhí)行環(huán)境的變量對象始終都是作用域中的最后一個對象。
根據(jù)這個概念圖解上面代碼:

在函數(shù)one創(chuàng)建時,它的作用域鏈中會填入一個全局對象,該全局對象包含了所有全局變量,當執(zhí)行流執(zhí)行到one()語句時,會創(chuàng)建函數(shù)one執(zhí)行環(huán)境。將函數(shù)one執(zhí)行環(huán)境。如果這個環(huán)境是函數(shù),則創(chuàng)建一個活動對象,然后此對象會被推入作用域鏈的前端,當函數(shù)執(zhí)行完畢后,活動對象也隨之銷毀。新的作用域鏈如下圖所示:

標識符解析是沿著作用域一級一級地搜素標識符的過程。搜素過程始終從作用域的前端開始,然后逐級地向后回溯,直到找到標識符為止,找不到,會導(dǎo)致錯誤發(fā)生。內(nèi)部環(huán)境可以通過作用域鏈訪問所有外部環(huán)境,但外部環(huán)境不能訪問內(nèi)部環(huán)境中任何變量和函數(shù)。這些環(huán)境之間的聯(lián)系是線性,有次序的。

這是初步了解作用域,如想更深入了解作用域,請看下面鏈接:
JavaScript作用域原理
JavaScript作用域鏈
由一道題圖解JavaScript的作用域
或者看《JavaScript權(quán)威指南》和《JavaScript高級程序設(shè)計》

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/86548.html

相關(guān)文章

  • 深入學(xué)習(xí)js之——作用域鏈

    摘要:開篇作用域是每種計算機語言最重要的基礎(chǔ)之一,因此要想深入的學(xué)習(xí)作用域和作用域鏈就是個繞不開的話題。這樣由多個執(zhí)行上下文的變量對象構(gòu)成的鏈表就叫做作用域鏈。這時候執(zhí)行上下文的作用域鏈,我們命名為至此,作用域鏈創(chuàng)建完畢。 開篇 作用域是每種計算機語言最重要的基礎(chǔ)之一,因此要想深入的學(xué)習(xí)JavaScript,作用域和作用域鏈就是個繞不開的話題。 在《深入學(xué)習(xí)js之—-執(zhí)行上下文棧》中我們提到...

    lemanli 評論0 收藏0
  • javascript中關(guān)于作用域和閉包

    摘要:在代碼執(zhí)行時,對應(yīng)的作用域鏈常常是保持靜態(tài)的。當語句執(zhí)行完畢后,會把作用域鏈恢復(fù)到原始狀態(tài)。在全局作用域中創(chuàng)建的函數(shù),其作用域鏈會自動成為全局作用域中的一員。 列表項目 前言 學(xué)習(xí)了javascript已經(jīng)很久了,關(guān)于這個語言中的這兩個特性也是早已耳熟能詳,但是在實際的使用的過程中或者是遇到相關(guān)的問題的時候,還是不能很好的解決。因此我覺得很有必要深入的學(xué)習(xí)并且記錄這個問題,以便在今后的...

    zacklee 評論0 收藏0
  • 深入學(xué)習(xí)js之——詞法作用域和動態(tài)作用

    摘要:在中的應(yīng)用采用詞法作用域,也就是靜態(tài)作用域。那什么又是詞法作用域或者靜態(tài)作用域呢請繼續(xù)往下看靜態(tài)作用域與動態(tài)作用域因為采用的是詞法作用域函數(shù)的作用域在函數(shù)定義的時候就決定了。 開篇 當我們在開始學(xué)習(xí)任何一門語言的時候,都會接觸到變量的概念,變量的出現(xiàn)其實是為了解決一個問題,為的是存儲某些值,進而,存儲某些值的目的是為了在之后對這個值進行訪問或者修改,正是這種存儲和訪問變量的能力將狀態(tài)給...

    shiweifu 評論0 收藏0
  • JS學(xué)習(xí)筆記(第4章)(變量、作用域和內(nèi)存問題)

    摘要:具體來說就是當執(zhí)行流進入下列任何一個語句時,作用域鏈就會得到加長語句的塊和語句。這兩個語句都會在作用域鏈的前端添加一個變量對象。對來說,會將指定的對象添加到作用域鏈中。 1. 基本類型和引用類型的值 JavaScript變量可以用來保存兩種類型的值:基本類性值和引用類性值。基本類型值源自以下5種基本數(shù)據(jù)類型:Undefined、Null、Boolean、Number和String。基本...

    linkin 評論0 收藏0
  • 理解JavaScript中的作用域和作用域鏈

    摘要:示例當一個函數(shù)創(chuàng)建后,它的作用域鏈會被創(chuàng)建此函數(shù)的作用域中可訪問的數(shù)據(jù)對象填充。每一個運行期上下文都和一個作用域鏈關(guān)聯(lián)。此時,作用域鏈中函數(shù)的所有局部變量所在的作用域?qū)ο髸煌坪螅L問代價變高了。 作用域 作用域就是變量與函數(shù)的可訪問范圍,即作用域控制著變量與函數(shù)的可見性和生命周期。在JavaScript中,變量的作用域有全局作用域和局部作用域兩種。 作用域鏈 函數(shù)對象有一個內(nèi)部屬性[...

    XanaHopper 評論0 收藏0

發(fā)表評論

0條評論

史占廣

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<