什么是執(zhí)行上下文钝诚?
js代碼解析執(zhí)行時所處的環(huán)境,顧名思義扎阶。
全局執(zhí)行上下文
只有一個洛姑,瀏覽器中全局對象就是window對象上沐,this指向全局對象
函數(shù)執(zhí)行上下文
只有函數(shù)被調(diào)用時才會創(chuàng)建執(zhí)行環(huán)境,可以有多個楞艾,多次参咙。
eval執(zhí)行上下文
js中不推薦用這個函數(shù)
執(zhí)行棧
棧的結(jié)構(gòu),后進先出产徊。先會創(chuàng)建一個全局的執(zhí)行上下文,push到當前的執(zhí)行棧頂蜀细,當調(diào)用新的函數(shù)則push新的函數(shù)執(zhí)行上下文舟铜,當執(zhí)行完后pop出執(zhí)行棧。
執(zhí)行上下文的創(chuàng)建過程
兩個階段創(chuàng)建階段和執(zhí)行階段
創(chuàng)建階段
確定this指向
全局執(zhí)行上下文中奠衔,this指向全局
函數(shù)執(zhí)行上下文中谆刨,this指向取決于當前調(diào)用的方式。
創(chuàng)建詞法環(huán)境
詞法環(huán)境有兩個組成部分
環(huán)境記錄是存儲變量和函數(shù)聲明的實際位置归斤。
對外部環(huán)境的引用意味著它可以訪問其外部詞法環(huán)境痊夭。
詞法環(huán)境有兩種類型
全局環(huán)境是一個沒有外部環(huán)境的詞法環(huán)境,外部環(huán)境應用為null脏里。擁有一個全局對象以及該對象擁有的對象和屬性她我,還有用戶自定義的全局變量。
函數(shù)環(huán)境,包括用戶在函數(shù)定義的變量存儲在環(huán)境記錄中番舆,包括argumnets對象酝碳。外部環(huán)境可能是全局環(huán)境,也可能是包含內(nèi)部函數(shù)的外部函數(shù)環(huán)境恨狈。
GlobalExectionContext = { // 全局執(zhí)行上下文
LexicalEnvironment: { // 詞法環(huán)境
EnvironmentRecord: { // 環(huán)境記錄
Type: "Object", // 全局環(huán)境
// 標識符綁定在這里
outer: <null> // 對外部環(huán)境的引用
}
}
FunctionExectionContext = { // 函數(shù)執(zhí)行上下文
LexicalEnvironment: { // 詞法環(huán)境
EnvironmentRecord: { // 環(huán)境記錄
Type: "Declarative", // 函數(shù)環(huán)境
// 標識符綁定在這里 // 對外部環(huán)境的引用
outer: <Global or outer function environment reference>
}
}
創(chuàng)建變量環(huán)境
變量環(huán)境也是一個詞法環(huán)境疏哗,因此它具有上面定義的詞法環(huán)境的所有屬性。
在 ES6 中禾怠,詞法環(huán)境和變量環(huán)境的區(qū)別在于前者用于存儲函數(shù)聲明和變量( let 和 const )綁定返奉,而后者僅用于存儲變量( var )綁定。
變量提升的原因
在創(chuàng)建階段吗氏,函數(shù)聲明存儲在環(huán)境中芽偏,而變量會被設置為 undefined(在 var 的情況下)或保持未初始化(在 let 和 const 的情況下)
執(zhí)行階段
進入執(zhí)行上下文
添加形參,變量聲明牲证,函數(shù)聲明哮针,
同一作用域下,函數(shù)提升比變量提升得更靠前.
代碼執(zhí)行
修改變量對象的值
內(nèi)存回收和內(nèi)存泄露
標記清除(常用)
標記清除算法將“不再使用的對象”定義為“無法到達的對象”。即從根部(在JS中就是全局對象)出發(fā)定時掃描內(nèi)存中的對象坦袍,凡是能從根部到達的對象十厢,保留。那些從根部出發(fā)無法觸及到的對象被標記為不再使用捂齐,稍后進行回收蛮放。
ES6 新出的兩種數(shù)據(jù)結(jié)構(gòu):WeakSet 和 WeakMap,表示這是弱引用奠宜,它們對于值的引用都是不計入垃圾回收機制的包颁。
常見的內(nèi)存泄露
內(nèi)存機制
基本類型:--> 棧內(nèi)存(不包含閉包中的變量)
引用類型:--> 堆內(nèi)存