基礎數據值在內存中佔據固定的大小空間,所以存在棧內存中
js的執行上下文順序借用了棧數據的存取方式,因此理解棧數據結構的原理和特色十分重要
方式:先進後出,後進先出(相似一盒乒乓球)前端
引用類型的值是對象,保存在堆內存中
堆數據結構是一種樹狀結構,它的存取方式,則與口紅色號同樣,只要有色號,就能找到對應的口紅
沒必要像乒乓球把上面的都拿出來才能獲取中間的某一個
比如JSON格式,key:value能夠是無序的,由於順序的不一樣不影響咱們的使用,咱們只關心色號編程
學習隊列數據結構的目的主要是爲了清晰的明白咱們js中事件循環(Event Loop)
隊列是一種先進先出的數據結構,正如排隊過安檢是同樣的。排在最前面的人必定是最早過安檢的人。數組
js執行上下文以後,會建立一個叫變量對象的特殊對象,js的基礎數據類型每每保存在變量對象中
基礎類型都是一些簡單的數據段,因此基礎數據類型是按值來訪問的,咱們能夠直接操做變量對象的實際值瀏覽器
js的引用類型儲存在堆內存中
js不容許咱們直接訪問內存中的數據
世界上咱們操做的是對象的引用而非實際的值
引用類型是按指針訪問的,這個指針指向內存中的實際地址。
所以,咱們操做引用類型複製時,它一樣會分配一個新的值保存在變量對象中,但這個個新值一樣指向內存中的實際值。改變一個,另外一個也會發生改變性能優化
分配你所需的內存
使用分配的內存(讀寫)
不須要時釋放,歸還數據結構
js擁有自動垃圾會回收機制
經常使用的使用標記清除法
當變量進入環境時,就將這個變量標記爲進入環境
垃圾回收機制運行中會給存儲在內存中的變量添加標記。而後,去掉環境中的變量以及環境中的變量被引用的標記,而在此以後再加上標記的變量將視爲被準備刪除的變量閉包
避免全局變量,使用完及時清空
局部變量,當函數執行安成以後很容易作出判斷,而後回收。app
執行上下文的順序是棧的數據結構方式,先進後出,後進先出
基礎數據類型的值存在棧內存中
引用數據類型的值存在堆內存中
隊列數據結構先進先出,後進後出。事件循環機制(Event Loop)
從一個變量向另外一個變量複製基本類型的值。會建立這個值的副本
從一個變量向另外一個變量複製引用類型的值,複製的實際上是指針,所以兩個變量最後指向同一個對象
解除變量的引用不只有助於消除循環引用現象,並且對垃圾收集也有好處。爲了確保有效地回收內存,應該及時解除再也不使用的全局對象、全局對象屬性以及循環引用變量的引用。函數式編程
每當控制器轉到可執行代碼的時候,就會進入一個執行上下文
它會造成一個做用域,js運行環境分爲3個種狀況
全局做用域
函數做用域
eval
執行上下文能夠理解成爲當前代碼的執行環境
所以js程序會出現多個執行上下文,因此js用棧的方式去處理它們。這個棧就叫作函數調用棧。棧底永遠是全局上下文,棧頂是當前執行上下文函數
建立變量對象(vo)
創建做用域鏈(scopechain)
肯定this指向
變量賦值
函數引用
執行其餘代碼
js是單線程
同步執行,只有棧頂的上下文處於執行中,其餘上下文須要等待,
全局上下文只有一個,它在瀏覽器關閉的時候出棧
函數執行上下文沒有數量限制
每次新函數被調用,就會有新的執行上下文被建立
變量對象是執行上下文的建立階段,會建立一個叫變量對象的基礎對象。js的基本類型每每都保存在變量對象中
變量對象的生命週期是根據執行上下文的生命週期去劃分的
建立階段:(變量提高階段,變量對象中的屬性不能訪問)
建立arguments對象
檢查function函數聲明建立屬性
檢查var變量聲明的屬性
執行階段(變量對象轉爲活動對象,屬性能夠被訪問,開始函數執行階段操做)
函數執行
變量賦值
彈出執行棧
活動對象和遍變量對象實際上是同一個的對象,區別在於執行的上下文的生命週期不一樣。
建立階段就是變量對象,變量對象的屬性不可被訪問。
執行階段就是活動對象,處於函數調用棧棧頂,也就是當前執行上下文。
這裏以瀏覽器爲例,全局對象是window
全局上下文存在一個特殊的地方,他的變量對象就是window,而這個特殊的對象在this指向一樣適用,this也指向window
全局上下文的生命週期與程序的生命週期同樣,只要瀏覽器窗口不關閉,它就會一直存在。其餘環境的上下文環境均可以訪問全局上下文
不存在變量提高
未聲明不能夠用 (暫時性死區)
做用域也就是詞法環境
詞法環境就是一中規範的類型,用於ECMAscript代碼的詞法嵌套結構來定義標識符與特定變量和函數的關聯
做用域是一種規則,做用域鏈是代碼在執行的過程當中,會動態變化的一條索引路徑
由當前環境和上層環境的一些列變量對象組成,它保證了當前執行環境對符合訪問權限的變量和函數的有序訪問
閉包是一種特殊的對象
由2部分組成
執行上下文(A)
以及執行上下文中建立的函數(B)
當B執行時,若是訪問了A中變量對象中的值。就像成了閉包
垃圾回收機制,js具備自動垃圾回收機制,當一個值在內存中失去引用時,垃圾回收器很快找到它,並回收釋放
函數執行上下文在執行完畢後,生命週期結束後,垃圾回收器就是收回其佔用的內存空間,但使用閉包就會阻止這個過程
全局的this,指向window
經過this綁定到全局對象
經過聲明綁定到變量對象,但在全局環境中,變量對象就是它自身
僅僅只有賦值操做,標識符會隱式綁定到全局對象
若是函數調用者,被某一個對象擁有。那麼該函數在調用時,this就是指向這個對象
若是函數內部獨立調用,那麼該函數內部的this,則指向window,嚴格模式下指向undefind
js內部提供了一種機制,容許咱們改變thiss的指向。他就是call和apply
這2個函數的第一個參數都是改變this的指向,區別:
在於第二個參數,call接受一個個參數傳入
apply接受數組傳入
接受參是一個個傳入
參數接受一個數組
返回一個函數
能夠選擇不當即執行
apply和call是當即執行
函數聲明
function fn(){}
函數表達式
let fn=function(){}
匿名函數
function add(fn,num){console.log(fn()+num)}
add(()=>90,10)
自執行函數
(()=>console.log(90))()
基本類型複製是值進行的複製,複製後互不影響
引用類型的複製是指針的複製。雖然也在變量對象上開闢新的空間,但實際指針同樣是堆內存中的地址,其中一個改變,另外一個也將改變,相互影響
函數是一等公民
只用表達式,不該語句
純函數
沒有辦法識別對象實例的類型
經過一個方法能夠去生成多個須要的對象
解決了重複代碼編寫
使用new的方式。經過原型鏈找到對象的實例對象
new的四部曲
建立一個對象
將這個對象的原型指向構造函數的原型
經過apply將構造函數的的this指向這個對象
最後返回這個對象
私有方法放實例中
共有方法放到原型鏈上
原型的好處是避免了同一功能性的方法寫多份。直接掛載到原型上便可
當咱們訪問實例對象中的屬性或者方法時,會優先訪問實例對象自身的屬性和方法。
原型鏈的訪問,其實跟做用域鏈有很大的類似之處,他們都是一次單向的查找過程。所以實例對象可以經過原型鏈,訪問處處於原型鏈上對象的全部屬性與方法
首先是構造函數的繼承
經過call將父級的指針指向子集
原型的繼承
能夠將子集的原型指向父級的實例
使用Object.create
configurable是否能夠被刪除
enumerable是否能夠被枚舉
writable是否能夠重寫
value該值具體多少,默認undefind
get訪問,獲取屬性值
set設置。設置屬性值
不能同時設置value、writable 與 get、set的值。
讀取屬性Object.getOwnPropertyDescriptor
js是單線程,這個線程擁有的惟一的事件循環
來自不一樣任務源的任務會進入到不一樣的任務隊列。其中setTimeout與setInterval是同源的。
事件執行的順序,決定了JavaScript代碼的執行順序
它從script(總體代碼)開始第一次循環,
以後全局上下文進入函數調用棧。直到調用棧清空(只剩全局),
而後執行全部的micro-task。
當全部可執行的micro-task執行完畢以後。
循環再次從macro-task開始,找到其中一個任務隊列執行完畢,而後再執行全部的micro-task,這樣一直循環下去。
其中每個任務的執行,不管是macro-task仍是micro-task,都是藉助函數調用棧來完成
setTimeout
setInterval
script(總體代碼)
Promise
XMind: ZEN - Trial Version