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

資訊專欄INFORMATION COLUMN

《javascript高級(jí)程序設(shè)計(jì)》筆記:變量對(duì)象與預(yù)解析

tyheist / 640人閱讀

摘要:檢查當(dāng)前上下文中的參數(shù),建立該對(duì)象下的屬性與屬性值。檢查當(dāng)前上下文的函數(shù)聲明,也就是使用關(guān)鍵字聲明的函數(shù)。如果該變量名的屬性已經(jīng)存在,為了防止同名的函數(shù)被修改為,則會(huì)直接跳過(guò),原屬性值不會(huì)被修改。

上一篇:《javascript高級(jí)程序設(shè)計(jì)》筆記:內(nèi)存與執(zhí)行環(huán)境

上篇文章中說(shuō)到:
(1)當(dāng)執(zhí)行流進(jìn)入函數(shù)時(shí),對(duì)應(yīng)的執(zhí)行環(huán)境就會(huì)生成
(2)執(zhí)行環(huán)境創(chuàng)建時(shí)會(huì)生成變量對(duì)象,確定作用域鏈,確定this指向
(2)每個(gè)執(zhí)行環(huán)境都有一個(gè)與之關(guān)聯(lián)的變量對(duì)象,環(huán)境中定義的所有變量和函數(shù)都保存在這個(gè)對(duì)象中

1. 變量對(duì)象

變量對(duì)象是在進(jìn)入執(zhí)行環(huán)境就確定下來(lái)的,顧名思義,變量對(duì)象是用于存儲(chǔ)在這個(gè)執(zhí)行環(huán)境中的所有變量和函數(shù)的一個(gè)對(duì)象。只是這個(gè)對(duì)象是用于解析器處理數(shù)據(jù)時(shí)使用,我們無(wú)法直接調(diào)用

下圖描述了執(zhí)行流在執(zhí)行環(huán)境中的執(zhí)行過(guò)程(執(zhí)行環(huán)境的生命周期)

(1)建立arguments對(duì)象。檢查當(dāng)前上下文中的參數(shù),建立該對(duì)象下的屬性與屬性值。

(2)檢查當(dāng)前上下文的函數(shù)聲明,也就是使用function關(guān)鍵字聲明的函數(shù)。在變量對(duì)象中以函數(shù)名建立一個(gè)屬性,屬性值為指向該函數(shù)所在內(nèi)存地址的引用。如果函數(shù)名的屬性已經(jīng)存在,那么該屬性將會(huì)被新的引用所覆蓋。

(3)檢查當(dāng)前上下文中的變量聲明,每找到一個(gè)變量聲明,就在變量對(duì)象中以變量名建立一個(gè)屬性,屬性值為undefined。如果該變量名的屬性已經(jīng)存在,為了防止同名的函數(shù)被修改為undefined,則會(huì)直接跳過(guò),原屬性值不會(huì)被修改。

總之:function聲明會(huì)比var聲明優(yōu)先級(jí)更高一點(diǎn)

下面通過(guò)具體的例子來(lái)看變量對(duì)象:

function test() {
  console.log(a);
  console.log(foo());

  var a = 1;
  function foo() {
    return 2;
  }
}

test();

當(dāng)執(zhí)行到test()時(shí)會(huì)生成執(zhí)行環(huán)境testEC,具體形式如下:

// 創(chuàng)建過(guò)程
testEC = {
  // 變量對(duì)象(variable object)
  VO: {},
  // 作用域鏈
  scopeChain: [],
  // this指向
  this: {}
}

僅針對(duì)變量對(duì)象來(lái)具體展開(kāi):

VO = {
  // 傳參對(duì)象
  arguments: {},
  // 在testEC中定義的function
  foo: "",
  // 在testEC中定義的var
  a: undefined
}

未進(jìn)入執(zhí)行階段之前,變量對(duì)象中的屬性都不能訪問(wèn)!但是進(jìn)入執(zhí)行階段之后,變量對(duì)象轉(zhuǎn)變?yōu)榱嘶顒?dòng)對(duì)象,里面的屬性都能被訪問(wèn)了,然后開(kāi)始進(jìn)行執(zhí)行階段的操作

// 執(zhí)行階段
VO ->  AO   // Active Object
AO = {
  arguments: {...},
  foo: function(){return 2},
  a: 1
}

最后我們將變量對(duì)象創(chuàng)建時(shí)的VO和執(zhí)行階段的AO整合到一起就可以得到整個(gè)執(zhí)行環(huán)境中代碼的執(zhí)行順序:

function test() {
  function foo() {
    return 2;
  }
  var a;
  console.log(a);// undefined
  console.log(foo());// 2
  a = 1;
}

test();

這個(gè)就是分步變量對(duì)象的創(chuàng)建和執(zhí)行階段來(lái)解讀預(yù)解析

2. 預(yù)解析

預(yù)解析分為變量提升和函數(shù)提升
變量提升:提升的是當(dāng)前變量的聲明,賦值還保留在原來(lái)的位置
函數(shù)提升:函數(shù)聲明,可以認(rèn)為是把整個(gè)函數(shù)體聲明了
函數(shù)表達(dá)式方式定義函數(shù)相當(dāng)于變量聲明 var fn = function(){}

一個(gè)簡(jiǎn)單的變量提升的例子

!function(){
  console.log(a);
  var a = 1;
}()

// 實(shí)際執(zhí)行順序
!function(){
  var a;
  console.log(a);
  a = 1;
}()

技巧:
將執(zhí)行過(guò)程手動(dòng)拆分成兩個(gè)步驟
1.創(chuàng)建階段:也稱作編譯階段,主要是變量的聲明和函數(shù)的定義(找var和function)
2.執(zhí)行階段:變量賦值和函數(shù)執(zhí)行

這樣看預(yù)解析還是比較容易的,但是涉及到命名沖突時(shí),又是怎樣的情況呢?

(1)一個(gè)函數(shù)和一個(gè)變量出現(xiàn)同名
情況一:變量只聲明了,但沒(méi)有賦值

!function(){
  var f;
  function f() {};
  console.log(f); // f(){}
}()

情況二:變量只聲明且賦值

!function(){
  console.log(f); // f(){}
  var f = 123;
  function f() {};
  console.log(f); // 123
}()

結(jié)論
1.一個(gè)函數(shù)和一個(gè)變量出現(xiàn)同名,如果是變量只聲明了,但沒(méi)有賦值,變量名會(huì)被忽略
2.一個(gè)函數(shù)和一個(gè)變量出現(xiàn)同名,變量聲明且賦值,賦值前值為函數(shù),賦值后為變量的值

(2)兩個(gè)變量出現(xiàn)同名

!function(){
  console.log(f); // undefined
  var f = 123;
  var f = 456;
  console.log(f); // 456
}()

結(jié)論
兩個(gè)變量出現(xiàn)同名,重復(fù)的var聲明無(wú)效,會(huì)被忽略,只會(huì)起到賦值的作用,前面賦值會(huì)被后面的覆蓋

(3)兩個(gè)函數(shù)出現(xiàn)同名

!function(){
  console.log(f); // function f(){return 456};
  function f(){return 123};
  function f(){return 456};
  console.log(f); // function f(){return 456};
}()

結(jié)論
兩個(gè)函數(shù)出現(xiàn)同名,由于javascript中函數(shù)沒(méi)有重載,前面的同名函數(shù)會(huì)被后面的覆蓋

(4)變量名與參數(shù)名相同

函數(shù)參數(shù)的本質(zhì)是什么?函數(shù)參數(shù)也是變量,相當(dāng)于在該函數(shù)的執(zhí)行環(huán)境內(nèi)最頂部聲明了實(shí)參

情況一:參數(shù)為變量,與變量命名沖突

(function (a) {
    console.log(a); // 100
    var a = 10;
    console.log(a); // 10
})(100);
// 相當(dāng)于
(function (a) {
  var a = 100;
    var a; // 重復(fù)聲明的var沒(méi)有意義,忽略
    console.log(a); // 100
    a = 10;
    console.log(a); // 10
})(100);

情況二:參數(shù)為函數(shù),與變量命名沖突

(function (a) {
    console.log(a); // function(){return 2}
    var a = 10;
    console.log(a); // 10
})(function(){return 2});
// 相當(dāng)于
(function (a) {
  var a = function(){return 2};
    var a; // 重復(fù)聲明的var沒(méi)有意義,忽略
    console.log(a); // function(){return 2}
    a = 10;
    console.log(a); // 10
})(function(){return 2});

情況三:參數(shù)為空,與變量命名沖突

(function (a) {
    console.log(a); // undefined
    var a = 10;
    console.log(a); // 10
})();
// 相當(dāng)于
(function (a) {
  var a;
    console.log(a); // undefined
    a = 10;
    console.log(a); // 10
})();

結(jié)論
1.重名的是一個(gè)變量,傳入了參數(shù)(變量或函數(shù)):
如果是在變量賦值之前,此時(shí)獲取的是:參數(shù)的值!

如果是在變量賦值之后,此時(shí)獲取的是:變量的值!

2.重名的是一個(gè)變量,但是沒(méi)有傳入?yún)?shù):

如果是在變量賦值之前,此時(shí)獲取的是:undefined!
如果是在變量賦值之后,此時(shí)獲取的是:變量的值!

(5)函數(shù)名與參數(shù)名相同

情況一:參數(shù)為變量,與函數(shù)命名沖突

(function (a) {
    console.log(a); // a(){}
    function a(){};
    console.log(a); // a(){}
})(100);
// 相當(dāng)于
(function (a) {
  var a = 100;
  function a(){};
    console.log(a); // a(){}
    console.log(a); // a(){}
})(100);

情況二:參數(shù)為函數(shù),與函數(shù)命名沖突

(function (a) {
    console.log(a); // function a(){return 1}
    function a(){return 1}
    console.log(a); // function a(){return 1}
})(function(){return 2});
// 相當(dāng)于
(function (a) {
  var a = function(){return 2};
  function a(){return 1};
    console.log(a); // function a(){return 1}
    console.log(a); // function a(){return 1}
})(function(){return 2});

情況三:參數(shù)為空,與函數(shù)命名沖突

(function (a) {
    console.log(a); // function a(){};
    function a(){};
    console.log(a); // function a(){};
})();
// 相當(dāng)于
(function (a) {
  var a;
  function a(){};
    console.log(a); // function a(){};
    console.log(a); // function a(){};
})();

注意:函數(shù)表達(dá)式聲明方式var f = function(){},在預(yù)解析中與普通的變量聲明無(wú)異,因?yàn)轭A(yù)解析階段主要是通過(guò)varfunction來(lái)區(qū)分函數(shù)與變量的

結(jié)論
傳參為函數(shù)時(shí),賦值前均為參數(shù)的值,賦值后為函數(shù)的值,傳空時(shí)均為函數(shù)的值

現(xiàn)在,我們回到變量對(duì)象中,在變量對(duì)象的創(chuàng)建階段(執(zhí)行流編譯階段),分別確定了arguments對(duì)象、函數(shù)聲明和變量聲明,其優(yōu)先級(jí)也是arguments>function>var,arguments就是參數(shù),反推上面變量提升的結(jié)論,同樣是成立的

經(jīng)典推薦:《javascript高級(jí)程序設(shè)計(jì)》筆記:原型圖解

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

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

相關(guān)文章

  • javascript高級(jí)程序設(shè)計(jì)筆記:內(nèi)存與執(zhí)行環(huán)境

    摘要:因此,所有在方法中定義的變量都是放在棧內(nèi)存中的當(dāng)我們?cè)诔绦蛑袆?chuàng)建一個(gè)對(duì)象時(shí),這個(gè)對(duì)象將被保存到運(yùn)行時(shí)數(shù)據(jù)區(qū)中,以便反復(fù)利用因?yàn)閷?duì)象的創(chuàng)建成本通常較大,這個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū)就是堆內(nèi)存。 上一篇:《javascript高級(jí)程序設(shè)計(jì)》筆記:繼承近幾篇博客都會(huì)圍繞著圖中的知識(shí)點(diǎn)展開(kāi) showImg(https://segmentfault.com/img/bVY0C4?w=1330&h=618);...

    fuyi501 評(píng)論0 收藏0
  • 《你不知道的javascript筆記_作用域與閉包

    摘要:建筑的頂層代表全局作用域。實(shí)際的塊級(jí)作用域遠(yuǎn)不止如此塊級(jí)作用域函數(shù)作用域早期盛行的立即執(zhí)行函數(shù)就是為了形成塊級(jí)作用域,不污染全局。這便是閉包的特點(diǎn)吧經(jīng)典面試題下面的代碼輸出內(nèi)容答案?jìng)€(gè)如何處理能夠輸出閉包方式方式下一篇你不知道的筆記 下一篇:《你不知道的javascript》筆記_this 寫在前面 這一系列的筆記是在《javascript高級(jí)程序設(shè)計(jì)》讀書(shū)筆記系列的升華版本,旨在將零碎...

    galaxy_robot 評(píng)論0 收藏0
  • JavaScript高級(jí)程序設(shè)計(jì)學(xué)習(xí)筆記三(基本語(yǔ)法)

    摘要:數(shù)據(jù)類型中有種簡(jiǎn)單數(shù)據(jù)類型也稱為基本數(shù)據(jù)類型和。在中非空字符串,非零數(shù)字,任意對(duì)象,都被認(rèn)為。而空字符串,和,,認(rèn)為是。用于表示整數(shù)和浮點(diǎn)數(shù)。標(biāo)識(shí)符由數(shù)字字母下劃線美元符組成,但首字母不能是數(shù)字。變量方法對(duì)象命名推薦駝峰法。 JavaScript語(yǔ)法 一.語(yǔ)法簡(jiǎn)介 因?yàn)镴avaScript語(yǔ)法和Java等語(yǔ)法非常類似。所以只是簡(jiǎn)單介紹一下。 大小寫 JavaScript是大小寫敏感的語(yǔ)...

    Mike617 評(píng)論0 收藏0
  • JavaScript高級(jí)程序設(shè)計(jì)筆記:基本概念

    摘要:一寫在前面最近重讀高級(jí)程序設(shè)計(jì),總結(jié)下來(lái),查漏補(bǔ)缺。但這種影響是單向的修改命名參數(shù)不會(huì)改變中對(duì)應(yīng)的值。這是因?yàn)閷?duì)象的長(zhǎng)度是由傳入的參數(shù)個(gè)數(shù)決定的,不是由定義函數(shù)時(shí)的命名參數(shù)的個(gè)數(shù)決定的。實(shí)際改變會(huì)同步,改變也會(huì)同步 一、寫在前面 最近重讀《JavaScript高級(jí)程序設(shè)計(jì)》,總結(jié)下來(lái),查漏補(bǔ)缺。 二、JS簡(jiǎn)介 2.1 JS組成 ECMAscript:以ECMA-262為基礎(chǔ)的語(yǔ)言,由...

    ygyooo 評(píng)論0 收藏0
  • 讀書(shū)筆記(01) - JSON - JavaScript高級(jí)程序設(shè)計(jì)

    摘要:用于把對(duì)象序列化字符串,在序列化對(duì)象時(shí),所有函數(shù)及原型成員都會(huì)被有意忽略,不體現(xiàn)在結(jié)果中。對(duì)第步返回的每個(gè)值進(jìn)行相應(yīng)的序列化。參考文檔高級(jí)程序設(shè)計(jì)作者以樂(lè)之名本文原創(chuàng),有不當(dāng)?shù)牡胤綒g迎指出。 showImg(https://segmentfault.com/img/bVburW1?w=658&h=494); JSON與JavaScript對(duì)象 JSON是一種表示結(jié)構(gòu)化數(shù)據(jù)的存儲(chǔ)格式,語(yǔ)...

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

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

0條評(píng)論

tyheist

|高級(jí)講師

TA的文章

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