成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

JS 作用域鏈

darry / 3612人閱讀

摘要:首先,在創(chuàng)建函數(shù)時(shí),作用域鏈內(nèi)就會(huì)先填入對(duì)象,圖片只例舉了全部變量中的一部分。然后,解釋器進(jìn)入函數(shù)的執(zhí)行環(huán)境,同樣的,首先填入父級(jí)的作用域鏈,就是的,包括了對(duì)象活動(dòng)對(duì)象。之后再把的活動(dòng)對(duì)象填入到作用域鏈最頂部,這就是的作用域鏈了。

之前學(xué)習(xí)JS函數(shù)部分時(shí),提到了作用域這一節(jié),但是因?yàn)槭褂貌牧蠒?shū)不同,今天在讀博客的時(shí)候發(fā)現(xiàn)其實(shí)還有一個(gè)知識(shí)點(diǎn)即作用域鏈,所以來(lái)寫(xiě)一些個(gè)人理解和認(rèn)識(shí)加深記憶。

引用:

JavaScript中的作用域鏈和閉包

JS的作用域和作用域鏈

結(jié)合代碼圖文講解JavaScript中的作用域與作用域鏈(主要)

先上考試代碼:

/==========例1==========
  
var scope="global";
function fn(){
  alert(scope);
  var scope="local";
  alert(scope);
}
fn();    //輸出結(jié)果?
alert(scope);//輸出結(jié)果?
  
//===========例2==========
  
var scope="global";
function fn(){
  alert(scope);
  scope="local";
  alert(scope);
}
fn();    //輸出結(jié)果?
alert(scope);//輸出結(jié)果?
  
//===========例3=========
  
var scope="global";
function fn(scope){
  alert(scope);
  scope="local";
  alert(scope);
}
fn();    //輸出結(jié)果?
alert(scope);//輸出結(jié)果?

我當(dāng)時(shí)做時(shí)候,卡在了第三題,后面明白了。

例1:只要記得變量聲明提升,例1應(yīng)該沒(méi)什么問(wèn)題,由于var變量聲明提前,所以當(dāng)調(diào)用fn()時(shí),第一個(gè)alert應(yīng)該彈出undefined,之后賦值,再alert"local"。而函數(shù)外的alert之前調(diào)用全局變量scope,彈出"global"。

    var scope = "global";
    function fn() {
        var scope;    
        alert(scope);            // undefined
        scope = "local";
        alert(scope);            // local
    };
    fn();
    alert(scope);                // global

例2:由于函數(shù)內(nèi)沒(méi)有var聲明變量,所以函數(shù)內(nèi)的scope指向的是全局變量scope,那alert當(dāng)然是全局變量的值啦——"global",之后賦值,再次alert,彈出"local"。此時(shí)全局變量scope已經(jīng)被重新賦值,所以函數(shù)外的alert彈出"local"

例3:這里先不提,后面就OK了。當(dāng)時(shí)我不知道如果傳入實(shí)參在函數(shù)內(nèi)是以什么方式存在,不傳入值為多少等。

板書(shū)ing

作用域鏈:

作用域鏈(Scope Chain)是javascript內(nèi)部中一種變量、函數(shù)查找機(jī)制,它決定了變量和函數(shù)的作用范圍,即作用域,理解作用域鏈的作用原理,上一篇文章的三個(gè)例子也就能理解了,從而知其然也知其所以然。
作用域鏈?zhǔn)荅CMAScript-262說(shuō)明文檔中的概念,javascript引擎是按ECMAScript-262說(shuō)明文檔去實(shí)現(xiàn)的,了解javascript引擎的工作原理有利于我們理解javascript的特性,但絕大多數(shù)js程序員不會(huì)去了解非常底層的技術(shù),所以閱讀ECMAScript-262說(shuō)明文檔,我們可以有一個(gè)直觀的方式去模擬javascript引擎的工作原理。
本文將通過(guò)1999年的ECMAScript-262-3th第三版來(lái)說(shuō)明作用域鏈的形成原理,將會(huì)介紹執(zhí)行環(huán)境,變量對(duì)象和活動(dòng)對(duì)象,arguments對(duì)象,作用域鏈等幾個(gè)概念。2009年發(fā)布了ECMAScript-262-5th第五版,不同的是取消了變量對(duì)象和活動(dòng)對(duì)象等概念,引入了詞法環(huán)境(Lexical Environments)、環(huán)境記錄(EnviromentRecord)等新的概念,所以?xún)蓚€(gè)版本的概念不要混淆了。

重點(diǎn)來(lái)了!

1. 執(zhí)行環(huán)境(Execution Contexts)

執(zhí)行環(huán)境(Execution Contexts)也被翻譯為執(zhí)行上下文,當(dāng)解析器進(jìn)入ECMAScript的可執(zhí)行代碼,解析器就進(jìn)入一個(gè)執(zhí)行環(huán)境,活動(dòng)的執(zhí)行環(huán)境組成一個(gè)邏輯上的棧,在這個(gè)邏輯棧頂部的執(zhí)行環(huán)境是當(dāng)前運(yùn)行的執(zhí)行環(huán)境。
注:ECMAScript中有三種可執(zhí)行代碼,GlobalFunctionEval,全局環(huán)境即是Global可執(zhí)行代碼,函數(shù)即是Function可執(zhí)行代碼。邏輯棧是一種特殊的數(shù)據(jù)存儲(chǔ)格式,特點(diǎn)是‘先進(jìn)后出,后進(jìn)先出",添加數(shù)據(jù)會(huì)先壓入邏輯棧頂部,刪除數(shù)據(jù)必須先從頂部開(kāi)始刪除。

變量對(duì)象(Variable Object)、活動(dòng)對(duì)象(Activation Object)和Arguments對(duì)象(Arguments Object)
(上面這句話(huà)很重要哦)

每個(gè)執(zhí)行環(huán)境都有一個(gè)與之關(guān)聯(lián)的變量對(duì)象,當(dāng)解析器進(jìn)入執(zhí)行環(huán)境時(shí),就會(huì)創(chuàng)建一個(gè)變量對(duì)象,變量對(duì)象保存著在當(dāng)前執(zhí)行環(huán)境中聲明的變量和函數(shù)的引用。

變量對(duì)象是一個(gè)抽象的概念,在不同的執(zhí)行環(huán)境中,變量對(duì)象有不同的身份,在解析器進(jìn)入任何執(zhí)行環(huán)境之前,就已經(jīng)創(chuàng)建了一個(gè)Global對(duì)象,當(dāng)解析器進(jìn)入全局執(zhí)行環(huán)境時(shí),Global對(duì)象就充當(dāng)變量對(duì)象,當(dāng)解析器進(jìn)入一個(gè)函數(shù)時(shí),就會(huì)創(chuàng)建一個(gè)活動(dòng)對(duì)象充當(dāng)變量對(duì)象。

我的理解是:解析器在執(zhí)行代碼時(shí),會(huì)遇到不同的執(zhí)行環(huán)境,此時(shí),會(huì)創(chuàng)建一個(gè)變量對(duì)象,里面存放了環(huán)境內(nèi)的變量和對(duì)象(函數(shù))引用。

當(dāng)執(zhí)行環(huán)境是變量,則會(huì)生成一個(gè)Global對(duì)象,此時(shí)變量對(duì)象就是Global對(duì)象

當(dāng)執(zhí)行環(huán)境是函數(shù),則會(huì)生成一個(gè)活動(dòng)對(duì)象(Activation Object)

2.解析器處理代碼時(shí)的兩個(gè)階段

我們都知道javascript解析器是一段一段解析處理代碼的,為毛?這就要涉及解析器處理代碼時(shí)的兩個(gè)階段,解析代碼和執(zhí)行代碼。
當(dāng)解析器進(jìn)入執(zhí)行環(huán)境時(shí),變量對(duì)象就會(huì)添加執(zhí)行環(huán)境中聲明的變量和函數(shù)作為它的屬性,這就意味著變量和函數(shù)在聲明之前已經(jīng)可用,變量值為undefined,這就是變量和函數(shù)聲明提升(Hoisting)的原因,與此同時(shí)作用域鏈和this確定,此過(guò)程為解析階段,俗稱(chēng)預(yù)解析。接著解析器開(kāi)始執(zhí)行代碼,為變量添加相應(yīng)值的引用,得到執(zhí)行結(jié)果,此過(guò)程為執(zhí)行階段。

我們還是用栗子談吧

var a=123;
var b="abc";
function c(){
  alert("11");
}


記得之前那句話(huà)嗎?在解析器進(jìn)入任何執(zhí)行環(huán)境之前,就已經(jīng)創(chuàng)建了一個(gè)Global對(duì)象,當(dāng)解析器進(jìn)入全局執(zhí)行環(huán)境時(shí),Global對(duì)象就充當(dāng)變量對(duì)象。一開(kāi)始,JavaScript解析器就已經(jīng)生成了一個(gè)Global Object來(lái)充當(dāng)變量對(duì)象,里面存放了全局環(huán)境里的變量,對(duì)象(函數(shù))等。就如上圖所示了,所以這也是為什么我們?cè)诤瘮?shù)內(nèi)部聲明變量時(shí),聲名會(huì)提前,賦值undefined的原因了。到現(xiàn)在為止,執(zhí)行到這就是預(yù)解析的過(guò)程也叫解析代碼。

然后開(kāi)始執(zhí)行賦值等操作,此過(guò)程就叫執(zhí)行過(guò)程。

再看這個(gè):

function testFn(a){
  var b="123";
  function c(){
    alert("abc");
  }
}
  
testFn(10);

解析器進(jìn)入函數(shù)執(zhí)行環(huán)境時(shí),則會(huì)創(chuàng)建一個(gè)活動(dòng)對(duì)象作為變量對(duì)象,活動(dòng)對(duì)象還會(huì)創(chuàng)建一個(gè)Arguments對(duì)象,arguments對(duì)象是一個(gè)參數(shù)集合,用來(lái)保存參數(shù),這就是我們寫(xiě)函數(shù)時(shí)可以使用arguments[0]等來(lái)使用參數(shù)的原因。

var a="123";
function testFn(b){
  var c="abc";
  
  function testFn2(){
    var d="efg";
    alert(a);
  }
  
  testFn2();
}
  
testFn(10);


首先,在創(chuàng)建函數(shù)testFn時(shí),作用域鏈內(nèi)([[scope]])就會(huì)先填入Global Object對(duì)象,圖片只例舉了全部變量中的一部分。
當(dāng)解析器進(jìn)入到testFn的執(zhí)行環(huán)境(執(zhí)行上下文)時(shí),在將函數(shù)的活動(dòng)對(duì)象添加到Global對(duì)象之前,注意是之前,形成一個(gè)作用域鏈。

然后,解釋器進(jìn)入testFn2函數(shù)的執(zhí)行環(huán)境,同樣的,首先填入父級(jí)的作用域鏈,就是testFn的[[scope]]],包括了Global對(duì)象、testFn活動(dòng)對(duì)象。之后再把testFn2的活動(dòng)對(duì)象填入到作用域鏈最頂部,這就是testFn2的作用域鏈了。

testFn2調(diào)用變量a時(shí),首先在當(dāng)前的testFn2活動(dòng)對(duì)象中查找,如果沒(méi)有找到就順著作用域鏈向上,在testFn活動(dòng)對(duì)象中查找變量a,如果沒(méi)有找到再順著作用域鏈向上查找,直到在最后Global對(duì)象中找到為止,否則報(bào)錯(cuò)。所以函數(shù)內(nèi)部可以調(diào)用外部環(huán)境的變量,外部環(huán)境不能調(diào)用函數(shù)內(nèi)部的變量,這就是作用域特性的原理。
大概總結(jié)一下:

執(zhí)行環(huán)境:(Execution Contexts)也被翻譯為執(zhí)行上下文,當(dāng)解析器進(jìn)入ECMAScript的可執(zhí)行代碼,解析器就進(jìn)入一個(gè)執(zhí)行環(huán)境,活動(dòng)的執(zhí)行環(huán)境組成一個(gè)邏輯上的棧,在這個(gè)邏輯棧頂部的執(zhí)行環(huán)境是當(dāng)前運(yùn)行的執(zhí)行環(huán)境。

ECMAScript中有三種可執(zhí)行代碼,Global、Function和Eval,全局環(huán)境即是Global可執(zhí)行代碼,函數(shù)即是Function可執(zhí)行代碼。邏輯棧是一種特殊的數(shù)據(jù)存儲(chǔ)格式,特點(diǎn)是‘先進(jìn)后出,后進(jìn)先出",添加數(shù)據(jù)會(huì)先壓入邏輯棧頂部,刪除數(shù)據(jù)必須先從頂部開(kāi)始刪除。

變量對(duì)象(Variable Object)、活動(dòng)對(duì)象(Activation Object)和Arguments對(duì)象(Arguments Object)

每個(gè)執(zhí)行環(huán)境都有一個(gè)與之關(guān)聯(lián)的變量對(duì)象,當(dāng)解析器進(jìn)入執(zhí)行環(huán)境時(shí),就會(huì)創(chuàng)建一個(gè)變量對(duì)象,變量對(duì)象保存著在當(dāng)前執(zhí)行環(huán)境中聲明的變量和函數(shù)的引用。

變量對(duì)象是一個(gè)抽象的概念,在不同的執(zhí)行環(huán)境中,變量對(duì)象有不同的身份,在解析器進(jìn)入任何執(zhí)行環(huán)境之前,就已經(jīng)創(chuàng)建了一個(gè)Global對(duì)象,當(dāng)解析器進(jìn)入全局執(zhí)行環(huán)境時(shí),Global對(duì)象就充當(dāng)變量對(duì)象,當(dāng)解析器進(jìn)入一個(gè)函數(shù)時(shí),就會(huì)創(chuàng)建一個(gè)活動(dòng)對(duì)象(Activation Object)充當(dāng)變量對(duì)象。

大致過(guò)程: 1. 自動(dòng)創(chuàng)建Global對(duì)象

(當(dāng)解析器進(jìn)入全局執(zhí)行環(huán)境時(shí),調(diào)用變量和函數(shù)時(shí)只在Global對(duì)象中查找。)

2. 解釋器進(jìn)入執(zhí)行環(huán)境(執(zhí)行上下文)

(也可理解為執(zhí)行函數(shù)時(shí)等等。)

3.生成變量對(duì)象

(每個(gè)執(zhí)行環(huán)境都有一個(gè)與之關(guān)聯(lián)的變量對(duì)象,當(dāng)解析器進(jìn)入執(zhí)行環(huán)境時(shí),就會(huì)創(chuàng)建一個(gè)變量對(duì)象,變量對(duì)象保存著在當(dāng)前執(zhí)行環(huán)境中聲明的變量和函數(shù)的引用。)

(變量對(duì)象是一個(gè)抽象的概念,在不同的執(zhí)行環(huán)境中,變量對(duì)象有不同的身身份。)

4. 創(chuàng)建作用域鏈(執(zhí)行過(guò)程中的預(yù)解析、執(zhí)行階段)

(每個(gè)執(zhí)行環(huán)境都有一個(gè)與之關(guān)聯(lián)的作用域鏈,當(dāng)解析器進(jìn)入執(zhí)行環(huán)境時(shí)被定義,作用域鏈?zhǔn)且粋€(gè)對(duì)象列表,用來(lái)檢索各個(gè)變量對(duì)象中的變量和函數(shù),這樣可以保證執(zhí)行環(huán)境有權(quán)訪問(wèn)哪些變量和函數(shù))

解析階段:當(dāng)解析器進(jìn)入執(zhí)行環(huán)境時(shí),變量對(duì)象就會(huì)添加執(zhí)行環(huán)境中聲明的變量和函數(shù)作為它的屬性,這就意味著變量和函數(shù)在聲明之前已經(jīng)可用,變量值為undefined,這就是變量和函數(shù)聲明提升(Hoisting)的原因,與此同時(shí)作用域鏈和this確定,此過(guò)程為解析階段,俗稱(chēng)預(yù)解析。
執(zhí)行階段:接著解析器開(kāi)始執(zhí)行代碼,為變量添加相應(yīng)值的引用,得到執(zhí)行結(jié)果,此過(guò)程為執(zhí)行階段。)

這里也就是說(shuō),變量對(duì)象先于作用域鏈創(chuàng)建前就以生成完畢?

5.按優(yōu)先級(jí)填入Global對(duì)象、活動(dòng)對(duì)象等 6. 整個(gè)作用域鏈創(chuàng)建完成

我們回到最初的題目,最后的例3中,調(diào)用fn時(shí),并沒(méi)有傳參,所以fn函數(shù)的活動(dòng)對(duì)象中沒(méi)有相關(guān)的鍵值(注意只是沒(méi)有值,但存在這個(gè)屬性),第一個(gè)alert彈出undefined,之后為其賦值,這時(shí)fn函數(shù)的活動(dòng)對(duì)象中的scope就有值了,之后alert調(diào)用,搜索時(shí)自然先從優(yōu)先級(jí)最高的fn活動(dòng)對(duì)象中尋找,然后彈出"local"。
而函數(shù)外的alert,依舊只有Global對(duì)象,其中的值未曾改變,所以彈出"global"

// undefined local  global

了解作用域和作用域鏈都更好的幫助了解閉包噢。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/83310.html

相關(guān)文章

  • 形象化模擬作用域鏈,深入理解js作用域、閉包

    摘要:至此作用域鏈創(chuàng)建完畢。好了,通過(guò)深入理解作用域鏈,我們能跟好的理解的運(yùn)行機(jī)制和閉包的原理。 前言 理解javascript中的作用域和作用域鏈對(duì)我們理解js這們語(yǔ)言。這次想深入的聊下關(guān)于js執(zhí)行的內(nèi)部機(jī)制,主要討論下,作用域,作用域鏈,閉包的概念。為了更好的理解這些東西,我模擬了當(dāng)一個(gè)函數(shù)執(zhí)行時(shí),js引擎做了哪些事情--那些我們看不見(jiàn)的動(dòng)作。 關(guān)鍵詞: 執(zhí)行環(huán)境 作用域 作用域鏈 變...

    txgcwm 評(píng)論0 收藏0
  • 深入學(xué)習(xí)js之——作用域鏈

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

    lemanli 評(píng)論0 收藏0
  • [學(xué)習(xí)筆記](méi) JavaScript 作用域鏈

    摘要:全局執(zhí)行環(huán)境的變量對(duì)象始終是作用域鏈中的最后一個(gè)變量對(duì)象。綜上,每個(gè)函數(shù)對(duì)應(yīng)一個(gè)執(zhí)行環(huán)境,每個(gè)執(zhí)行環(huán)境對(duì)應(yīng)一個(gè)變量對(duì)象,而多個(gè)變量對(duì)象構(gòu)成了作用域鏈,如果當(dāng)前執(zhí)行環(huán)境是函數(shù),那么其活動(dòng)對(duì)象在作用域鏈的前端。 1.幾個(gè)概念 先說(shuō)幾個(gè)概念:函數(shù)、執(zhí)行環(huán)境、變量對(duì)象、作用域鏈、活動(dòng)對(duì)象。這幾個(gè)東東之間有什么關(guān)系呢,往下看~ 函數(shù) 函數(shù)大家都知道,我想說(shuō)的是,js中,在函數(shù)內(nèi)部有兩個(gè)特殊...

    ?xiaoxiao, 評(píng)論0 收藏0
  • JS基礎(chǔ)知識(shí):變量對(duì)象、作用域鏈和閉包

    摘要:前言這段時(shí)間一直在消化作用域鏈和閉包的相關(guān)知識(shí)。而作用域鏈則是這套規(guī)則這套規(guī)則的具體運(yùn)行。是變量對(duì)象的縮寫(xiě)那這樣放有什么好處呢我們知道作用域鏈保證了當(dāng)前執(zhí)行環(huán)境對(duì)符合訪問(wèn)權(quán)限的變量和函數(shù)的有序訪問(wèn)。 前言:這段時(shí)間一直在消化作用域鏈和閉包的相關(guān)知識(shí)。之前看《JS高程》和一些技術(shù)博客,對(duì)于這些概念的論述多多少少不太清楚或者不太完整,包括一些大神的技術(shù)文章。這也給我的學(xué)習(xí)上造成了一些困惑,...

    Keven 評(píng)論0 收藏0
  • JS 執(zhí)行上下文棧 / 作用域鏈

    摘要:每一個(gè)執(zhí)行上下文可以訪問(wèn)的對(duì)象包括自身的作用域和父執(zhí)行上下文的作用域和父父執(zhí)行上下文作用域直到全局作用域,這就產(chǎn)生了作用域鏈。語(yǔ)句結(jié)束后,作用域鏈恢復(fù)正常。 0、自己理解 代碼執(zhí)行或函數(shù)調(diào)用生成執(zhí)行上下文(只有當(dāng)前執(zhí)行上下文有執(zhí)行權(quán)),該執(zhí)行上下文內(nèi)只能訪問(wèn)當(dāng)前執(zhí)行上下文的變量、函數(shù)和上一級(jí)執(zhí)行上下文中的變量、函數(shù),激活下一個(gè)執(zhí)行上下文的時(shí)候執(zhí)行權(quán)轉(zhuǎn)移到新的執(zhí)行上下文,形成執(zhí)行上下文棧...

    yunhao 評(píng)論0 收藏0
  • JS中的new和作用域鏈

    摘要:同時(shí)構(gòu)造函數(shù)內(nèi)部的被指定為。這時(shí)的作用域鏈?zhǔn)怯傻幕顒?dòng)對(duì)象和全局對(duì)象組成的。在被調(diào)用時(shí),它自身的活動(dòng)對(duì)象被創(chuàng)建,然后添加到了中存儲(chǔ)著的作用域鏈的最前方。當(dāng)函數(shù)執(zhí)行完畢時(shí)活動(dòng)對(duì)象會(huì)被從該作用域鏈上刪除。參考自運(yùn)算符作用域原理譯函數(shù)的作用域鏈 new的運(yùn)行機(jī)制 當(dāng)代碼new Animal(cat)執(zhí)行時(shí): var obj=Object.create(Animal.prototype); 傳...

    calx 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<