JavaScript的執行過程

javascript的執行過程

整個JavaScript的代碼運行能夠分爲 <創建執行上下文> 和 <代碼執行> 兩個階段;
其中執行上下文的創建包括:javascript

  • 初始化this
  • 變量對象VO(活動對象AO)
  • 做用域鏈SC;

代碼執行時會實例化VO或AO對象中的變量;具體以下:java

執行上下文 execution context

執行上下文會有三種狀況:算法

  • 全局執行上下文、
  • 函數執行上下文、
  • eval執行上下文;

引擎會在執行時創建執行上下文堆棧;執行上下文會初始化三個對象:this、變量對象VO/活動對象AO、做用域鏈。數組

this對象

使用easy模式來斷定this的指向,做爲對象屬性方法調用時指向對象,做爲全局方法使用指向window,函數中的this主要是依賴於調用者,在進行賦值等操做時注意this的指向丟失問題;瀏覽器

變量對象VO/激活對象AO

看有些資料說變量對象和活動對象是一回事兒,甚至有些資料說其差別在於活動對象多了arguments屬性。昨天的學習課程讓我對這個問題有了清晰的認識。變量對象其實是一個邏輯上的概念,是邏輯上做用域鏈的組成元素。而在實際的實踐中則大部分時間由活動對象充當這個角色。在全局上下文中,全局對象window充當變量對象,全局上下文的做用域鏈中存放全局對象;在函數進入執行上下文以前,會生成一個活動對象,將arguments、參數、函數聲明、變量聲明按這個順序添加到變量對象之中。app

在VO/AO中存在同名變量時的覆蓋順序是:應該是函數聲明>函數形參>變量;也就是在這裏完成變量聲明、函數形參和函數聲明的提早的;而變量聲明不會進行復制操做,函數形參也沒有複製操做一說;須要注意的是函數聲明會把函數體帶入,此時函數會創建相應的隱式[[scope]]數組屬性,這個數組指向的當前上下文的做用域鏈,須要注意的是這裏只有函數聲明,不會有函數表達式,函數聲明都是在跟語句下,而函數表達式都是在執行代碼時創建的;函數

函數中的激活對象最開始只有一個對象;就是arguments這個對象,有着length、callee等屬性;學習

其實VO/AO都是做爲當前上下文的做用於鏈的組成元素,this

做用域鏈scope chain

全局執行上下文的做用域鏈就是[window];spa

函數的做用域鏈就是 [當前上下文的VO/AO,自身的scope內容];這裏函數的隱式[[scope]]是在函數被聲明或者被表達式執行時創建的,也就是上文說的當前執行上下文的做用域鏈;

變量實例化在代碼執行前,上下文創建後來完成的

原型

全部的對象都是經過函數建立的,首先看看函數和new操做時都發生了什麼:其中隱式[[prototype]]也就是瀏覽器中認爲的 _protp_這個對象

prototype原型

函數也是一種對象。他也是屬性的集合,你也能夠對函數進行自定義屬性。javascript本身就默認的給函數一個屬性------prototype。對,每一個函數都有一個屬性叫作prototype。這個prototype的屬性值是一個對象(屬性的集合,再次強調!),默認的只有一個叫作constructor的屬性,指向這個函數自己。
圖片描述

進行new Object()時的狀況
圖片描述

隱式原型"_proto_"也是[[prototype]]
每一個函數function都有一個prototype,即原型。這裏再加一句話------每一個對象都有一個_proto_,可成爲隱式原型。這個_proto_是一個隱藏的屬性,javascript不但願開發者用到這個屬性值,有的低版本瀏覽器甚至不支持這個屬性值。

每一個對象都有一個_proto_屬性,指向建立該對象的函數的prototype。

圖片描述

一樣自定義函數的prototype。自定義函數的prototype本質上就是和 var obj = {} 是同樣的,都是被Object建立,因此它的_proto_指向的就是Object.prototype。

可是Object.prototype確實一個特例------它的_proto_指向的是null,切記切記!

一樣以前說了函數也是對象,那麼函數的_proto_是誰?是Function.prototype,而Function.prototype指向的對象也是對象,它的_proto_是否是也指向Object.prototype?看一張大圖慢慢理解:
圖片描述
其實在JavaScript中的instanceof就是跟着原型鏈這麼來進行斷定的;

建立function算法 函數有prototype屬性是個對象和[[Prototype]]也就是_proto_屬性

F=new Object();建立對象

F.[[class]]="Function";指定類型

F.[[Prototype]]=Function.prototype;把_proto_指向函數的prototype

F.[[Call]]=internalCall; 內部調用

F.[[Construct]]=internalConstructor; 內部構造

F.[[Scope]]=currentContext.Scope Chain.concat(); 把[[Scope]]是當前執行上下文做用域

F.length=FormalParameterNum

//DontDelete ReadOnly DontEnum

temp=new Object();  初始化prototype

temp.constructor=F; 初始化prototype下的constructor

//DontEnum DontDelete

F.prototype=temp; 完成初始化

return F 返回

new函數

function internalConstructor(parameters){

O=new Object();

O.[[Class]]="Object";

O.[[Prototype]]=Object.prototype;

R=F.[[Call]].apply(O,parameters);

return O;

}
相關文章
相關標籤/搜索