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

資訊專欄INFORMATION COLUMN

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

tyheist / 669人閱讀

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

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

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

1. 變量對象

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

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

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

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

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

總之:function聲明會比var聲明優(yōu)先級更高一點

下面通過具體的例子來看變量對象:

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

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

test();

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

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

僅針對變量對象來具體展開:

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

未進入執(zhí)行階段之前,變量對象中的屬性都不能訪問!但是進入執(zhí)行階段之后,變量對象轉(zhuǎn)變?yōu)榱嘶顒訉ο?,里面的屬性都能被訪問了,然后開始進行執(zhí)行階段的操作

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

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

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

test();

這個就是分步變量對象的創(chuàng)建和執(zhí)行階段來解讀預解析

2. 預解析

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

一個簡單的變量提升的例子

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

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

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

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

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

!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.一個函數(shù)和一個變量出現(xiàn)同名,如果是變量只聲明了,但沒有賦值,變量名會被忽略
2.一個函數(shù)和一個變量出現(xiàn)同名,變量聲明且賦值,賦值前值為函數(shù),賦值后為變量的值

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

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

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

(3)兩個函數(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é)論
兩個函數(shù)出現(xiàn)同名,由于javascript中函數(shù)沒有重載,前面的同名函數(shù)會被后面的覆蓋

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

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

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

(function (a) {
    console.log(a); // 100
    var a = 10;
    console.log(a); // 10
})(100);
// 相當于
(function (a) {
  var a = 100;
    var a; // 重復聲明的var沒有意義,忽略
    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});
// 相當于
(function (a) {
  var a = function(){return 2};
    var a; // 重復聲明的var沒有意義,忽略
    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
})();
// 相當于
(function (a) {
  var a;
    console.log(a); // undefined
    a = 10;
    console.log(a); // 10
})();

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

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

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

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

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

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

(function (a) {
    console.log(a); // a(){}
    function a(){};
    console.log(a); // a(){}
})(100);
// 相當于
(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});
// 相當于
(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(){};
})();
// 相當于
(function (a) {
  var a;
  function a(){};
    console.log(a); // function a(){};
    console.log(a); // function a(){};
})();

注意:函數(shù)表達式聲明方式var f = function(){},在預解析中與普通的變量聲明無異,因為預解析階段主要是通過varfunction來區(qū)分函數(shù)與變量的

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

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

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

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

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

相關(guān)文章

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

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

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

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

    galaxy_robot 評論0 收藏0
  • JavaScript高級程序設(shè)計學習筆記三(基本語法)

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

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

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

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

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

    mengbo 評論0 收藏0

發(fā)表評論

0條評論

tyheist

|高級講師

TA的文章

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