????JS 是 一種 弱類型的動態(tài)語言甸饱,何為動態(tài)語言:運(yùn)行過程中需要檢查數(shù)據(jù)類型的語?稱為動態(tài)語言沦童;相對應(yīng)的?使用之前就需要確認(rèn)其變量數(shù)據(jù)類型的稱為靜態(tài)語言,比如 C叹话、JAVA偷遗。
? ? 1.?弱類型意味著你不需要告訴 JS 引擎這個或那個變量是什么數(shù)據(jù)類型,JS 引擎在運(yùn)?代 碼的時候自己會計(jì)算出來渣刷。?
? ? 2. 動態(tài)意味著你可以使?同?個變量保存不同類型的數(shù)據(jù)鹦肿。
????JavaScript 的數(shù)據(jù)類型分為:簡單數(shù)據(jù)類型(值類型)?和?復(fù)雜數(shù)據(jù)類型(引用類型)
? ??簡單數(shù)據(jù)類型:字符串(string),布爾(boolean)辅柴,數(shù)字(number)箩溃,undefined,null碌嘀,BigInt涣旨, Symbol
? ??復(fù)雜數(shù)據(jù)類型:對象(Object)
JS數(shù)據(jù)存儲機(jī)制
? ? 內(nèi)存空間
? ? ? ? JS 執(zhí)行過程種,主要有三種類型內(nèi)存空間股冗,分別是 代碼空間霹陡,棧空間 和 堆空間。
? ? ? ? 椗朊蓿空間 和 堆空間
? ? ? ? ? ? 首先看一段代碼攒霹,分析其調(diào)用棧
? ? ? ? ? ? 當(dāng)代碼執(zhí)行完 前面兩行的時候,調(diào)用棧內(nèi)的情況浆洗,由于 a 和 b 是 值類型的 數(shù)據(jù)催束, 內(nèi)存開辟一個空間 存放 a? 和 b 的值。
? ? ? ? 當(dāng)執(zhí)行到第三行 伏社,引用類型的值抠刺,調(diào)用棧情況又是如何:
? ? ? ? 引用類型的 數(shù)據(jù) 是放在 堆空間的,椪空間只是 保存了對象的 引用地址速妖。JS 需要訪問該數(shù)據(jù)的時候,通過棧中的 應(yīng)用地址來訪問聪黎。
? ? ? ? 總結(jié): 1. 簡單類型的數(shù)據(jù)值都是直接保存在“椇比荩”中的,引用類型的值是存放在“堆”中挺举;
? ? ? ? ? ? ? ? ? ? 2. 簡單類型傳值杀赢,復(fù)雜類型(引用類型)傳址:簡單類型的賦值會完整復(fù)制變量值烘跺,復(fù)雜類型的賦值是復(fù)制引用地址湘纵。
? ???? ? 那么為什么不把所有的數(shù)據(jù)都存放到棧中呢?
? ? ? ? ? ? JS 引擎使用棧 來維護(hù)執(zhí)行上下文的狀態(tài)滤淳,如果所有的數(shù)據(jù)都存放在 椢嗯纾空間,導(dǎo)致棽备溃空間過大铺敌,會影響 上下文的切換效率,進(jìn)而影響整個程序的 執(zhí)行效率屁擅。比如勘伺,當(dāng)我們執(zhí)行完一個函數(shù)淑翼,只需要將 函數(shù)的執(zhí)行上下文彈出棧, 將 指針往 下移動到 上一個執(zhí)行上下文就可以了,函數(shù)的執(zhí)行上下文 會被回收逗栽。
? ? ? ? ? ? 所以 通常情況下,椩萘酰空間都不會 太大谈况,只要存放一些 簡單類型的小數(shù)據(jù),而 將 復(fù)雜類型的數(shù)據(jù) 放到 空間很大的 堆 空間早抠。
? ? ? ? 接下來
? ? ? ? d 的 賦值過程霎烙,指向了堆中的同一個地址,修改 c 的 值,d 也會改變悬垃。
再談閉包
? ? ? ? 1 當(dāng) JS 運(yùn)行到 foo 函數(shù)游昼,創(chuàng)建執(zhí)行上下文;
? ? ? ? 2 編譯中有 bar 函數(shù) 尝蠕,JS 引擎對 bar 做一次快速的詞法掃描酱床,發(fā)現(xiàn)該函數(shù)調(diào)用了 foo中的變量 a, 由于是 內(nèi)部函數(shù) 引用了外部函數(shù)的變量趟佃,所以 JS 引擎判斷這是 一個閉包扇谣,在堆 空間創(chuàng)造了一個 Closure(foo) 對象保存 a 變量。
? ? ? ? 當(dāng)執(zhí)行 foo 函數(shù)闲昭,閉包就產(chǎn)生了罐寨,foo 函數(shù)執(zhí)行完畢, 返回的 bar 函數(shù)用到了 closure(foo)對象序矩,所以 即使 foo 函數(shù)執(zhí)行結(jié)束鸯绿,closure(foo)依然被用到。在調(diào)用bar 函數(shù)的時候簸淀,創(chuàng)建的執(zhí)行上下文 就包含了?closure(foo)瓶蝴。
????總結(jié):產(chǎn)生閉包的核心有兩步:第一步是需要預(yù)掃描內(nèi)部函數(shù);第二步是把內(nèi)部函數(shù)引用的外部變量保 存到堆中租幕。
? ? 總結(jié)
? ? ? ? JS 8中數(shù)據(jù)類型分為兩大類: 值類型 和 引用類型舷手,值類型數(shù)據(jù)存放在 棧中,引用類型數(shù)據(jù)存放在 堆中劲绪;將一個 值類型的變量 a 賦值 給 b男窟,a 和 b 相互獨(dú)立,互不影響贾富;但是 引用類型 a 賦值給 b歉眷, 那么 它們指向同一個數(shù)據(jù), a 和 b 相互影響颤枪。