站長資訊網(wǎng)
        最全最豐富的資訊網(wǎng)站

        簡約JavaScript中的變量對象

        JavaScript內(nèi)功之變量對象

        簡約JavaScript中的變量對象

        目錄

        • 前言
        • 一、變量對象
        • 二、全局變量對象
        • 三、函數(shù)變量對象
        • 寫在最后

        (免費學(xué)習(xí)推薦:javascript視頻教程

        前言

        JavaScript編程的時候總避免不了聲明函數(shù)和變量,以成功構(gòu)建我們的系統(tǒng),但是解釋器是如何并且在什么地方去查找這些函數(shù)和變量呢?我們引用這些對象的時候究竟發(fā)生了什么?

        在上篇《JavaScript中的執(zhí)行上下文》中我們提到了一部分,當(dāng) JavaScript 代碼執(zhí)行一段可執(zhí)行代碼(executable code)時,會創(chuàng)建對應(yīng)的執(zhí)行上下文(execution context)。

        對于每個執(zhí)行上下文,都有三個重要屬性:

        • 變量對象(Variable object,VO)
        • 作用域鏈(Scope chain)
        • this

        簡約JavaScript中的變量對象

        一、變量對象

        在函數(shù)上下文中,我們用活動對象(activation object, AO)來表示變量對象。

        活動對象和變量對象其實是一個東西

        1. 變量對象是規(guī)范上的或者說是引擎實現(xiàn)上的,不可在 JavaScript 環(huán)境中訪問
        2. 只有到當(dāng)進入一個執(zhí)行上下文中,這個執(zhí)行上下文的變量對象才會被激活,所以才叫 activation object 吶,而只有被激活的變量對象,也就是活動對象上的各種屬性才能被訪問。

        這里附上一張貘大對于兩者關(guān)系的回答:
        簡約JavaScript中的變量對象

        我們可以將變量對象的創(chuàng)建過程用代碼模擬一下:

        1.我們用普通的對象來表示變量對象

        var VO = {}; // 變量對象

        2.而變量對象是執(zhí)行上下文的一個屬性:

        activeContext = {   VO: {     // 上下文數(shù)據(jù)(var, FD, function arguments)   }};

        3.當(dāng)我們遇到下面的代碼時:

        var a = 10;function func(x){     var b = 20;}func(30);

        4.對應(yīng)的變量對象應(yīng)該是:

        // 全局變量對象VO(Global) = {     a: 10,     func: reference to function plus(){}}// func函數(shù)上下文的變量對象VO(func functionContext) = {   x: 30,   b: 20};

        因為不同執(zhí)行上下文下的變量對象稍有不同,所以我們分開來說。

        簡約JavaScript中的變量對象

        二、全局變量對象

        我們先了解一個概念,叫全局對象。在 W3School 中也有介紹:

        全局對象是預(yù)定義的對象,作為 JavaScript 的全局函數(shù)和全局屬性的占位符。通過使用全局對象,可以訪問所有其他所有預(yù)定義的對象、函數(shù)和屬性。

        1.可以通過 this 引用,在客戶端 JavaScript 中,全局對象就是 Window 對象。

        console.log(this); //Window

        2.全局對象是由 Object 構(gòu)造函數(shù)實例化的一個對象。

        console.log(this instanceof Object); // true

        3.預(yù)定義了一堆,嗯,一大堆函數(shù)和屬性。

        // 都能生效console.log(Math.random());  //隨機數(shù)console.log(this.Math.random()); //隨機數(shù)

        4.作為全局變量的宿主(很牛的樣子)

        var a = 1;console.log(this.a);// 1

        5.客戶端 JavaScript 中,全局對象有 window 屬性指向自身。

        var a = 1;console.log(window.a); // 1this.window.b = 2;console.log(this.b); // 2

        而全局上下文中的變量對象就是全局對象!

        簡約JavaScript中的變量對象

        三、函數(shù)上下文中的變量對象

        在函數(shù)執(zhí)行上下文中,VO是不能直接訪問的,此時由活動對象(activation object,縮寫為AO)扮演VO的角色。

        VO(functionContext) === AO

        活動對象是在進入函數(shù)上下文時刻被創(chuàng)建的,它通過函數(shù)的arguments屬性初始化。arguments屬性的值是Arguments對象:

        AO = {     arguments: <ArgO>}

        Arguments對象是活動對象的一個屬性,它包括如下屬性:

        1. callee — 指向當(dāng)前函數(shù)的引用
        2. length — 真正傳遞的參數(shù)個數(shù)
        3. properties-indexes (字符串類型的整數(shù)) 屬性的值就是函數(shù)的參數(shù)值(按參數(shù)列表從左到右排列)。
        4. properties-indexes內(nèi)部元素的個數(shù)等于arguments.length. properties-indexes 的值和實際傳遞進來的參數(shù)之間是共享的。

        我們來看下面代碼:

        function foo(x, y, z) {     // 聲明的函數(shù)參數(shù)數(shù)量arguments (x, y, z)   alert(foo.length); // 3     // 真正傳進來的參數(shù)個數(shù)(only x, y)   alert(arguments.length); // 2     // 參數(shù)的callee是函數(shù)自身   alert(arguments.callee === foo); // true     // 參數(shù)共享     alert(x === arguments[0]); // true   alert(x); // 10     arguments[0] = 20;   alert(x); // 20     x = 30;   alert(arguments[0]); // 30     // 不過,沒有傳進來的參數(shù)z,和參數(shù)的第3個索引值是不共享的    z = 40;   alert(arguments[2]); // undefined     arguments[2] = 50;   alert(z); // 40  }  foo(10, 20);

        3.1 執(zhí)行過程

        執(zhí)行上下文的代碼會分成兩個階段進行處理:分析和執(zhí)行,我們也可以叫做:

        1. 進入執(zhí)行上下文
        2. 代碼執(zhí)行

        3.2 進入執(zhí)行上下文

        當(dāng)進入執(zhí)行上下文時,這時候還沒有執(zhí)行代碼,

        變量對象會包括:

        1. 函數(shù)的所有形參 (如果是函數(shù)上下文)

          • 由名稱和對應(yīng)值組成的一個變量對象的屬性被創(chuàng)建
          • 沒有實參,屬性值設(shè)為 undefined
        2. 函數(shù)聲明

          • 由名稱和對應(yīng)值(函數(shù)對象(function-object))組成一個變量對象的屬性被創(chuàng)建
          • 如果變量對象已經(jīng)存在相同名稱的屬性,則完全替換這個屬性
        3. 變量聲明

          • 由名稱和對應(yīng)值(undefined)組成一個變量對象的屬性被創(chuàng)建;
          • 如果變量名稱跟已經(jīng)聲明的形式參數(shù)或函數(shù)相同,則變量聲明不會干擾已經(jīng)存在的這類屬性

        舉個例子:

        function foo(a) {   var b = 2;   function c() {}   var d = function() {};    b = 3;}foo(1);

        在進入執(zhí)行上下文后,這時候的 AO 是:

        AO = {     arguments: {         0: 1,         length: 1     },     a: 1,     b: undefined,     c: reference to function c(){},     d: undefined}

        3.3 代碼執(zhí)行

        在代碼執(zhí)行階段,會順序執(zhí)行代碼,根據(jù)代碼,修改變量對象的值

        還是上面的例子,當(dāng)代碼執(zhí)行完后,這時候的 AO 是:

        AO = {     arguments: {         0: 1,         length: 1     },     a: 1,     b: 3,     c: reference to function c(){},     d: reference to FunctionExpression "d"}

        到這里變量對象的創(chuàng)建過程就介紹完了,讓我們簡潔的總結(jié)我們上述所說:

        1. 全局上下文的變量對象初始化是全局對象;
        2. 函數(shù)上下文的變量對象初始化只包括 Arguments 對象;
        3. 在進入執(zhí)行上下文時會給變量對象添加形參、函數(shù)聲明、變量聲明等初始的屬性值;
        4. 在代碼執(zhí)行階段,會再次修改變量對象的屬性值;

        思考題

        最后讓我們看幾個例子:

        1.第一題

        function foo() {     console.log(a);     a = 1;}foo(); // ???function bar() {     a = 1;     console.log(a);}bar(); // ???

        第一段會報錯:Uncaught ReferenceError: a is not defined

        第二段會打?。?code>1。

        這是因為函數(shù)中的 “a” 并沒有通過 var 關(guān)鍵字聲明,所有不會被存放在 AO 中。

        第一段執(zhí)行 console 的時候, AO 的值是:

        AO = {     arguments: {         length: 0     }}

        沒有 a 的值,然后就會到全局去找,全局也沒有,所以會報錯。

        當(dāng)?shù)诙螆?zhí)行 console 的時候,全局對象已經(jīng)被賦予了 a 屬性,這時候就可以從全局找到 a 的值,所以會打印 1。

        2.第二題

        console.log(foo);function foo(){     console.log("foo");}var foo = 1;

        會打印函數(shù),而不是 undefined 。

        這是因為在進入執(zhí)行上下文時,首先會處理函數(shù)聲明,其次會處理變量聲明,如果如果變量名稱跟已經(jīng)聲明的形式參數(shù)或函數(shù)相同,則變量聲明不會干擾已經(jīng)存在的這類屬性。

        相關(guān)免費學(xué)習(xí)推薦:javascript(視頻)

        贊(0)
        分享到: 更多 (0)
        網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
        主站蜘蛛池模板: 麻豆国内精品久久久久久 | 少妇人妻偷人精品无码视频| 国内精品手机在线观看视频| 午夜欧美精品久久久久久久| 久久国产香蕉一区精品| 2024最新国产精品一区| 国产精品视频白浆免费视频 | 国产精品一区二区av不卡| 精品午夜久久福利大片| 国产午夜精品久久久久免费视| 亚洲AV永久无码精品一区二区 | 久久r热这里有精品视频| 精品视频无码一区二区三区| 亚洲一区精品无码| 久久人搡人人玩人妻精品首页| 99R在线精品视频在线播放| 国产成人精品免费视频大| 四虎成人精品无码| 四虎国产精品免费久久| 国产综合成人色产三级高清在线精品发布| 国产日韩精品欧美一区喷水| 成人国产精品动漫欧美一区| 97精品国产手机| 亚洲av成人无码久久精品| 欧美日韩精品一区二区视频| 国产精品H片在线播放| 欧美精品在线一区| 国产欧美久久久精品| 国产2021精品视频免费播放| 国产在线精品无码二区| 人妻精品久久久久中文字幕69| 亚洲精品美女久久久久99| 日本国产精品久久| 欧美成人精品一区二三区在线观看| 国产精品视频九九九| 国产午夜精品一区二区三区小说| 国产精品99爱免费视频| 国产精品福利在线观看免费不卡| 欧美精品一本久久男人的天堂| 国内精品手机在线观看视频| 影音先锋国产精品国语对白|