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

資訊專欄INFORMATION COLUMN

JavaScript的預(yù)編譯過程與作用域

ziwenxie / 736人閱讀

摘要:詞法作用域是一種靜態(tài)作用域這個(gè)例子的結(jié)果按靜態(tài)作用域來分析執(zhí)行函數(shù),先從函數(shù)內(nèi)部查找是否有局部變量,如果沒有,就根據(jù)書寫的位置,查找上面一層的代碼,也就是等于,所以結(jié)果會(huì)打印。靜態(tài)作用域,決定的是作用域鏈的順序。

博客原文地址:https://finget.github.io/2018/03/01/javascriptPrecompile/
看不明白的地方歡迎提問,有理解的不對(duì)的地方希望能夠指出來

JavaScript在運(yùn)行時(shí),要經(jīng)歷三步

語法分析 2.預(yù)編譯 3.解析執(zhí)行(自上而下)

JavaScript預(yù)編譯

先思考這么一個(gè)題

function fn (a) {
  console.log(a);

  var a = 123;

  console.log(a);
  
  function a(){};

  console.log(a);

  var b =function (){};

  console.log(b);
}
fn(1);
預(yù)編譯四部曲

創(chuàng)建AO對(duì)象 Activation Object(執(zhí)行期上下文)

找形參和變量聲明,將變量和形參名作為AO屬性名,值為undefined

將實(shí)參值和形參統(tǒng)一

在函數(shù)體里面找函數(shù)聲明,值賦予函數(shù)體

這四步的權(quán)重比4>3>2>1,也就是一個(gè)覆蓋的過程.
函數(shù)聲明在變量聲明的前面

函數(shù)聲明才存在變量提升。即function a(){};,而var b =function (){};不會(huì)提升。
詳細(xì)分析 先看一個(gè)面試中常遇到的問題
console.log(a); // function a(){}
var a = 1;
function a(){};

逐行執(zhí)行,在AO中是:

AO{
  a: undefied
}
AO{
  a: function(){}
}
換一換
var a = 1;
console.log(a); // 1
function a(){};

逐行執(zhí)行,在AO中是:

AO{
  a: undefied
}

AO{
  a: function(){}
}

// js是自上而下執(zhí)行的,先執(zhí)行var a = 1; 所有AO中的a就被覆蓋
AO{
  a: 1
}
按步驟分析文章開頭的例子

第一步

AO{
}

第二步

AO{
  a: undefined,
  b: undefined
}

第三步

AO{
  a: 1,
  b: undefined
}

第四步

AO{
  a: function a(){},
  b: undefined
}
解釋執(zhí)行

執(zhí)行的時(shí)候:

AO{
  a: function a(){},
  b: undefined
}
// a = 123;
AO{
  a: 123,
  b: undefined
}
結(jié)果:
function fn (a) {
  console.log(a); // function(){}

  var a = 123;

  console.log(a); // 123
  
  function a(){};

  console.log(a); // 123

  var b =function (){};
 
  console.log(b); // function(){}
}
fn(1);
加入window,全局環(huán)境
global = 100;
function fn() {
  console.log(global);
  global = 200;
  console.log(global);
  var global = 300;
}
fn();
var global;

在全局環(huán)境中會(huì)生成一個(gè) GO對(duì)象 (Global Object),還是按照上面的四步執(zhí)行。

GO {
  global: undefined  
}

// 執(zhí)行到 global = 100 :

GO {
  global: 100  
}

當(dāng)執(zhí)行fn之前會(huì)先生成一個(gè)AO:

AO {
  global: undefined  
}

所以第一次打印globalundefined。

這個(gè)時(shí)候雖然全局變量中的global已經(jīng)是100,但是fn函數(shù)中自己有global變量,所以不會(huì)引用全局中的。

當(dāng)執(zhí)行到global = 200 :

AO {
  global: 200  
}

所以第二次打印global200

這里這中情況涉及到了‘作用域’。
作用域
這里參考的是https://github.com/mqyqingfeng/Blog/issues/3,可以去詳細(xì)看看
JavaScript 采用的是詞法作用域,函數(shù)的作用域在函數(shù)定義的時(shí)候就決定了。

詞法作用域是一種靜態(tài)作用域

var value = 1;

function foo() {
    console.log(value);
}

function bar() {
    var value = 2;
    foo();
}

bar();

這個(gè)例子的結(jié)果:1

按靜態(tài)作用域來分析

執(zhí)行 foo 函數(shù),先從 foo 函數(shù)內(nèi)部查找是否有局部變量 value,如果沒有,就根據(jù)書寫的位置,查找上面一層的代碼,也就是 value 等于 1,所以結(jié)果會(huì)打印 1。

JavaScript的預(yù)編譯過程來分析

這里有全局的環(huán)境:

// 這里我就寫最后一步了
GO {
  value: 1,
  foo: function() {console.log(value)},
  bar: function() {var value = 2; foo()}
}
// 函數(shù)在執(zhí)行時(shí)也會(huì)生成自己的AO
fooAO{
  // 沒有
}
barAO{
  value: 2,
  foo: foo()
}

foo函數(shù)中沒有定義value,所以它會(huì)到它所在的上一層去找,并不會(huì)去bar里面找

把這個(gè)題做一個(gè)小小的改變:
var value = 1;

function foo() {
    console.log(value);
}

function bar() {
    value = 2;
    foo();
}

bar();

這樣結(jié)果就是2了。

在bar函數(shù)中不定義value,而是讓它直接改變value的值,他自己沒有定義,它也會(huì)去全局GO里面找,這樣bar里面的value和全局中的value就是同一個(gè)內(nèi)存中的數(shù),當(dāng)代碼執(zhí)行到value=2,再執(zhí)行foo()時(shí),全局中的value也是2,所以輸出2。在第一種,情況中,var value=2只改變了barAO中的值。

再來,我們?cè)僮円幌拢?/b>
function foo() {
    console.log(value);
}

function bar() {
    value = 2;
    foo();
}

bar();

結(jié)果還是2.

這次我們沒有全局定義value,在bar中也沒有定義,而是直接賦值。在JavaScript中如果一個(gè)變量未聲明就直接賦值,那么這個(gè)變量就是個(gè)全局變量。所以GO中會(huì)定義一個(gè)value:2,foo也沒有去bar里面找value。

靜態(tài)作用域,決定的是作用域鏈的順序。
最后思考一個(gè)問題
function fn(){
  var a = b = 100;
  console.log(window.a);
  console.log(window.b);
}
var a = b =100;
先將100賦值給b,即b=100,此時(shí)b沒有聲明就被賦值。

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

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

相關(guān)文章

  • JavaScript-預(yù)編譯

    摘要:預(yù)編譯發(fā)生在函數(shù)執(zhí)行前也就是說函數(shù)執(zhí)行時(shí),預(yù)編譯已經(jīng)結(jié)束。五總結(jié)理解預(yù)編譯需要明白變量函數(shù)聲明和變量賦值。預(yù)編譯階段,只進(jìn)行變量函數(shù)聲明,不會(huì)進(jìn)行變量的初始化即變量賦值,所有變量的值都是變量賦值是在解釋執(zhí)行階段才進(jìn)行的。 一、JS的概念 JavaScript ( JS ) 是一種具有函數(shù)優(yōu)先的輕量級(jí)解釋型或即時(shí)編譯型的編程語言。 二、JS語言特點(diǎn) 2.1 單線程 (1)JavaScri...

    Aldous 評(píng)論0 收藏0
  • JS編譯之 LHS RHS(你不知道的JavaScript 小記一)

    摘要:關(guān)于兩個(gè)專業(yè)術(shù)語的討論起自對(duì)你不知道的一書的閱讀學(xué)習(xí)。遇到,編譯器會(huì)詢問作用域是否已經(jīng)有一個(gè)該名稱的變量存在于同一個(gè)作用域的集合中。摘錄來自你不知道的。 JS 編譯之 LHS RHS 一、前言 最近和朋友聊技術(shù)的時(shí)候,聊到 LHS RHS,我竟然沒聽說過 沒聽說過。。。 于是成功引起了我的好奇心。 關(guān)于兩個(gè)專業(yè)術(shù)語的討論起自對(duì)《你不知道的JavaScript》一書的閱讀學(xué)習(xí)。 二、編譯...

    Cristic 評(píng)論0 收藏0
  • javascript作用

    摘要:結(jié)果結(jié)果函數(shù)定義式函數(shù)表達(dá)式結(jié)果預(yù)編譯是以段為處理單元結(jié)果作用域鏈代碼優(yōu)化在標(biāo)識(shí)符解析的時(shí)候,查找全局變量是最慢的,所以盡量使用局部變量。全局變量的被調(diào)用兩次,查找該變量必須遍歷整個(gè)作用域鏈,耗費(fèi)時(shí)間可以把它存儲(chǔ)到局部變量里再使用。 作用域?qū)傩允窃诙x函數(shù)的時(shí)候決定的,不是在調(diào)用函數(shù)的時(shí)候決定。 JavaScript中的函數(shù)運(yùn)行在它們被定義的作用域里,而不是它們被執(zhí)行的作用域里。 ...

    Cheriselalala 評(píng)論0 收藏0
  • JavaScript 作用學(xué)習(xí)筆記

    摘要:每一個(gè)運(yùn)行期上下文都和一個(gè)作用域鏈關(guān)聯(lián)。這個(gè)對(duì)象將被推入作用域鏈的頭部,這意味著函數(shù)的所有局部變量現(xiàn)在處于第二個(gè)作用域鏈對(duì)象中,因此訪問代價(jià)更高了。在代碼塊內(nèi)部,函數(shù)的所有局部變量將會(huì)被放在第二個(gè)作用域鏈對(duì)象中。 參考: Javascript作用域原理 理解 JavaScript 作用域和作用域鏈 JavaScript 作用域 作用域就是變量與函數(shù)的可訪問范圍,即作用域控制著變量與函數(shù)...

    趙連江 評(píng)論0 收藏0
  • 詳解JavaScript函數(shù)模式

    摘要:函數(shù)表達(dá)式又名匿名函數(shù)為變量賦的值是函數(shù)定義本身。在語言里任何匿名函數(shù)都是屬于對(duì)象。這種情況下,就叫做回調(diào)函數(shù)。如上面代碼示例展示了文檔單擊事件時(shí)以冒泡模式傳遞給回調(diào)函數(shù)的特別適用于事件驅(qū)動(dòng)編程,因?yàn)榛卣{(diào)模式支持程序以異步方式運(yùn)行。 JavaScript設(shè)計(jì)模式的作用是提高代碼的重用性,可讀性,使代碼更容易的維護(hù)和擴(kuò)展 在javascript中,函數(shù)是一類對(duì)象,這表示他可以作為參數(shù)傳遞...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<