這一篇簡單的說一說js的函數執行和js的執行上下文的概念,以前在個人博客裏邊也提到過
js的堆棧隊列,
這一篇打算單獨的拿出來講一說html
一段能夠執行的代碼在被執行的時候,會建立一個函數的執行上下文
執行上下文裏邊有三個重要的屬性分別是瀏覽器
執行上下文是跟函數相關的,執行上下文分爲兩個階段函數
建立階段
執行階段
首先建立階段this
掃描變量和函數(肯定變量環境)
肯定this指向
肯定詞法環境
簡單說一下詞法環境和變量環境的區別,我我的理解的就是說詞法環境是包含變量環境的spa
在js裏邊原型鏈你們都不陌生 ,js在當前的對象裏邊找不到所使用的屬性的話會去他的上一級去找
直到Object,再找不到就會undefined ,這裏邊 當前對象的做用域就是他的變量環境,而詞法環境則是與之關聯的的執行上下文中聲明的變量指針
在建立階段 函數的聲明會被儲存在當前的變量環境之中,var的變量的話則會被設置成undefined
,因此咱們在聲明以前就能夠訪問到var聲明的變量 ,but他是一個undfinedcode
而後就是執行階段了htm
這個時候已經完成了對全部變量的分配,開始執行代碼對象
什麼是變量對象,變量對象就是與執行上下文相關得數據得一個做用域,這裏邊存儲了在這個上下文裏邊定義的而變量和函數聲明blog
函數聲明的時候會在建立階段的時候聲明一個函數指針
故名思與函數上下文,在函數被執行的時候建立,那麼全局上下文是何時被建立的呢,首先咱們要知道一個概念就是,全局對象
console.log(this);
能夠嘗試着去打印一下this,以下圖能夠看到,window對象裏邊有不少咱們經常使用或者常見的屬性和方法
固然也有一些其餘的狀況this並非指向的window對象,this指向 這個東西,咱們會在下邊說
用 instanceof 輸出一下this 會發現也是一個object
console.log(this instanceof Object);
因此說全局對象是一個object的實例化對象
因此說說白了全局上下文就是在一開始就被建立的,全局上下文是由在瀏覽器關閉或者刷新的時候纔會銷燬, 而後這個window對象其實就是全局上下文的變量對象
函數上下文和上邊所說的意思差很少,可是,啊,可是,在函數上下文中的時候,函數裏邊的變量對象是活動對象,他的英文名字叫作 actiation object ,大面上看的意思就是說只有進入了這個執行上下文中的時候,也就是說執行到了這個函數的時候,其中的變量對象纔會被激活,纔會能被訪問,在沒有執行到這個函數的時候,其屬性是不能訪問的,這裏是和全局上下文不一樣的。
function foo(a) { var b = 2; function c() {} var d = function() {}; b = 3; } foo(1);
首先看這段代碼,上邊也說了,函數執行有兩個階段建立階段和執行階段
首先進如執行上下文,進入建立階段
上邊這段代碼在建立階段是這樣得
{ arguments: { 0: 1, length: 1 }, a: 1, b: undefined, c: reference to function c(){}, d: undefined }
而後函數的而執行階段,這個時候就該幹嗎幹嗎了,函數裏邊聲明的變量,賦值等等的會在這裏根據代碼,修改變量的值
{ arguments: { 0: 1, length: 1 }, a: 1, b: 3, c: reference to function c(){}, d: reference to FunctionExpression "d" }
得出一個結論,函數的執行上下文裏邊在初始化的時候只包含一個arguments對象,其餘的屬性是沒有值的,爲了直觀一點 ,舉個例子
function foo() { console.log(a); a = 1; } foo(); function bar() { a = 1; console.log(a); } bar();
好比說這個在foo函數的上下文裏邊打印a, 可是foo 裏邊沒有用var聲明,下邊的a就找不到因此會打印一個 a is not defined。
可是第二個的話會打印一個1,由於搭載因以前,全局對象裏邊已經有了a屬性
最後就是,在上文提到
c: reference to function c(){}, d: reference to FunctionExpression "d"
在上下文建立的時候,變量是不會覆蓋這種聲明的,好比說
console.log(foo); function foo(){ console.log("foo"); } var foo = 1;
會打印這個函數,可是, 啊,可是,若是是這樣
function foo(){ console.log("foo"); } var foo = 1; console.log(foo);
這樣的話就變成了剛纔所說的賦值了 ,會打印1
以上是我對js函數的執行與上下文的一些認識,剛從博客園搬過來,有不足的但願指正