站長資訊網
最全最豐富的資訊網站

簡約JavaScript中的變量對象

JavaScript內功之變量對象

簡約JavaScript中的變量對象

目錄

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

(免費學習推薦:javascript視頻教程

前言

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

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

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

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

簡約JavaScript中的變量對象

一、變量對象

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

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

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

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

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

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

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

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

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

3.當我們遇到下面的代碼時:

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

4.對應的變量對象應該是:

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

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

簡約JavaScript中的變量對象

二、全局變量對象

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

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

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

console.log(this); //Window

2.全局對象是由 Object 構造函數實例化的一個對象。

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

3.預定義了一堆,嗯,一大堆函數和屬性。

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

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中的變量對象

三、函數上下文中的變量對象

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

VO(functionContext) === AO

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

AO = {     arguments: <ArgO>}

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

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

我們來看下面代碼:

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

3.1 執行過程

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

  1. 進入執行上下文
  2. 代碼執行

3.2 進入執行上下文

當進入執行上下文時,這時候還沒有執行代碼,

變量對象會包括:

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

    • 由名稱和對應值組成的一個變量對象的屬性被創建
    • 沒有實參,屬性值設為 undefined
  2. 函數聲明

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

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

舉個例子:

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

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

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

3.3 代碼執行

在代碼執行階段,會順序執行代碼,根據代碼,修改變量對象的值

還是上面的例子,當代碼執行完后,這時候的 AO 是:

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

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

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

思考題

最后讓我們看幾個例子:

1.第一題

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

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

第二段會打印:1

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

第一段執行 console 的時候, AO 的值是:

AO = {     arguments: {         length: 0     }}

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

當第二段執行 console 的時候,全局對象已經被賦予了 a 屬性,這時候就可以從全局找到 a 的值,所以會打印 1。

2.第二題

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

會打印函數,而不是 undefined 。

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

相關免費學習推薦:javascript(視頻)

贊(0)
分享到: 更多 (0)
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
久久精品一区二区三区中文字幕 | 久久精品无码精品免费专区| 男女男精品视频网站在线观看| 日韩精品视频在线观看免费| 国产精品毛片无遮挡高清| 国内精品久久久久影院老司| 亚洲国产日产无码精品| 99re视频精品全部免费| 久久国产精品99久久小说| 97久久国产综合精品女不卡| 精品国产人成亚洲区| 亚洲国产一成久久精品国产成人综合 | 国产精品综合一区二区三区| 国产亚洲精品VA片在线播放| 国产精品岛国久久久久| 久久久久国产精品人妻| 国产精品嫩草影院久久| 青青草原综合久久大伊人精品| 亚洲精品在线免费看| 人妻少妇精品一区二区三区| 免费观看四虎精品国产永久| 日韩精品久久不卡中文字幕 | 日韩三级电影视频| 亚洲AV日韩AV无码污污网站| 日韩毛片一级好特黄| 日韩精品视频免费观看| 日韩一区二区a片免费观看| 亚洲日韩AV一区二区三区四区| 日韩免费视频播播| 亚洲av午夜成人片精品电影| 日韩精品人妻系列无码av东京| 野花国产精品入口| 国产精品深夜福利免费观看| 国产成人综合日韩精品无码| 国产在视频线在精品| 国产av无码久久精品| 日韩精品一区二区三区老鸭窝| 日韩精品电影在线| 国产精品99精品视频网站| 国内精品久久久久影院网站| 国内精品免费视频精选在线观看|