成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

前端進(jìn)擊的巨人(二):棧、堆、隊(duì)列、內(nèi)存空間

edgardeng / 2988人閱讀

摘要:中有三種數(shù)據(jù)結(jié)構(gòu)棧堆隊(duì)列。前端進(jìn)擊的巨人一執(zhí)行上下文與執(zhí)行棧,變量對(duì)象中解釋執(zhí)行棧時(shí),舉了一個(gè)乒乓球盒子的例子,來演示棧的存取方式,這里再舉個(gè)栗子搭積木。對(duì)于基本類型,棧中存儲(chǔ)的就是它自身的值,所以新內(nèi)存空間存儲(chǔ)的也是一個(gè)值。

面試經(jīng)常遇到的深淺拷貝,事件輪詢,函數(shù)調(diào)用棧,閉包等容易出錯(cuò)的題目,究其原因,都是跟JavaScript基礎(chǔ)知識(shí)不牢固有關(guān),下層地基沒打好,上層就是豆腐渣工程,新人小白,踏實(shí)踩土才是關(guān)鍵。

打地基第二篇:本篇我們將對(duì)JavaScript數(shù)據(jù)結(jié)構(gòu)的知識(shí)點(diǎn)詳解一二。

JavaScript中有三種數(shù)據(jù)結(jié)構(gòu): 棧(stack) 、堆(heap)、 隊(duì)列(queue)。

棧(stack)

棧的特點(diǎn)是"LIFO,即后進(jìn)先出(Last in, first out)"。數(shù)據(jù)存儲(chǔ)時(shí)只能從頂部逐個(gè)存入,取出時(shí)也需從頂部逐個(gè)取出?!肚岸诉M(jìn)擊的巨人(一):執(zhí)行上下文與執(zhí)行棧,變量對(duì)象》中解釋執(zhí)行棧時(shí),舉了一個(gè)乒乓球盒子的例子,來演示棧的存取方式,這里再舉個(gè)栗子搭積木。

舉個(gè)栗子:乒乓球盒子/搭建積木

JavaScript中Array數(shù)組模擬棧:

var arr = [1, 2, 3, 4, 5];

arr.push(6); // 存入數(shù)據(jù) arr -> [1, 2, 3, 4, 5, 6]
arr.pop();   // 取出數(shù)據(jù) arr -> [1, 2, 3, 4, 5]
堆(heap)

堆的特點(diǎn)是"無序"key-value"鍵值對(duì)"存儲(chǔ)方式。

舉個(gè)栗子:書架存書

我們想要在書架上找到想要的書,最直接的方式就是通過查找書名,書名就是我們的key。拿著這把key,就可以輕松檢索到對(duì)應(yīng)的書籍。

"堆的存取方式跟順序沒有關(guān)系,不局限出入口"。

隊(duì)列 (queue)

隊(duì)列的特點(diǎn)是是"FIFO,即先進(jìn)先出(First in, first out)" 。
數(shù)據(jù)存取時(shí)"從隊(duì)尾插入,從隊(duì)頭取出"。

"與棧的區(qū)別:棧的存入取出都在頂部一個(gè)出入口,而隊(duì)列分兩個(gè),一個(gè)出口,一個(gè)入口"。

舉個(gè)栗子:排隊(duì)取餐

JavaScript中Array數(shù)組模擬隊(duì)列:

var arr = [1, 2, 3, 4, 5];

// 隊(duì)尾in
arr.push(6);    // 存入 arr -> [1, 2, 3, 4, 5, 6]
// 隊(duì)頭out
arr.shift();    // 取出 arr -> [2, 3, 4, 5, 6]
棧、堆、隊(duì)列在JavaScript中的應(yīng)用 1. 代碼運(yùn)行方式(棧應(yīng)用/函數(shù)調(diào)用棧)

《前端進(jìn)擊的巨人(一):執(zhí)行上下文與執(zhí)行棧,變量對(duì)象》詳解了JavaScript運(yùn)行時(shí)的函數(shù)調(diào)用過程,而其中執(zhí)行棧(函數(shù)調(diào)用棧)就是用到棧的數(shù)據(jù)結(jié)構(gòu)。

JavaScript中函數(shù)的執(zhí)行過程,其實(shí)就是一個(gè)入棧出棧的過程:

當(dāng)腳本要調(diào)用一個(gè)函數(shù)時(shí),JS解析器把該函數(shù)推入棧中(push)并執(zhí)行

當(dāng)函數(shù)運(yùn)行結(jié)束后,JS解析器將它從堆棧中推出(pop)

具體執(zhí)行過程可翻閱上篇文章《前端進(jìn)擊的巨人(一):執(zhí)行上下文與執(zhí)行棧,變量對(duì)象》,這里不再贅述。

2. 內(nèi)存存儲(chǔ)(棧、堆)

JavaScript中變量類型有兩種:

基礎(chǔ)類型(Undefined, Null, Boolean, Number, String, Symbol)一共6種

引用類型(Object)

基礎(chǔ)類型的值保存在棧中,這些類型的值有固定大小,"按值來訪問";

引用類型的值保存在堆中,棧中存儲(chǔ)的是引用類型的引用地址(地址指針),"按引用訪問",引用類型的值沒有固定大小,可擴(kuò)展(一個(gè)對(duì)象我們可以添加多個(gè)屬性)。

3. 事件輪詢(隊(duì)列)

JavaScript中事件輪詢(Event Loop)的執(zhí)行機(jī)制,就是采用隊(duì)列的存取方式,因事件輪詢(Event Loop)也是JS基礎(chǔ)中的一個(gè)比較難理解的知識(shí)點(diǎn),后續(xù)另開一篇章再作詳細(xì)探究。

深淺拷貝

將一個(gè)變量的值賦值給另一個(gè)變量,相當(dāng)于在棧內(nèi)存中創(chuàng)建了一個(gè)新的內(nèi)存空間,然后從棧中復(fù)制值,存儲(chǔ)到這個(gè)新空間中。對(duì)于基本類型,棧中存儲(chǔ)的就是它自身的值,所以新內(nèi)存空間存儲(chǔ)的也是一個(gè)值。直接改變新變量的值,不會(huì)影響到舊變量的值,因?yàn)樗麄冎荡鎯?chǔ)的內(nèi)存空間不同。

// 基本類型復(fù)制變量
var a = 10;
var b = a;
b = 20;

a // 10
b // 20

而對(duì)于引用類型來說,同樣是復(fù)制棧中存儲(chǔ)的值。但是棧存儲(chǔ)的只是其引用地址,其具體的值存儲(chǔ)在堆中。變量復(fù)制僅復(fù)制棧中存儲(chǔ)的值,不會(huì)復(fù)制堆中存儲(chǔ)的值,所以新變量在棧中的值是一個(gè)地址指針。

// 引用類型復(fù)制變量
var a = { age: 27 };
var b = a;
b.age = 29;

a.age == b.age; // 29

可見,變量復(fù)制賦值,都屬于棧存儲(chǔ)拷貝,因此深淺拷貝可以這樣區(qū)分:

"淺拷貝:棧存儲(chǔ)拷貝"

"深拷貝:棧堆存儲(chǔ)拷貝"

深拷貝會(huì)同時(shí)開辟新的棧內(nèi)存,堆內(nèi)存空間。

// 利用JSON對(duì)象方法實(shí)現(xiàn)深拷貝
var a = { age: 27 };
var b = JSON.parse(JSON.stringify(a));
b.age = 29;

a.age // 27
b.age // 29
函數(shù)傳參數(shù)是按值傳遞?按引用傳遞?
var person = {
 age: 27
};
function foo (person) {
  person.age = 29;
}
foo(person);
person.age // 29;

函數(shù)調(diào)用時(shí),會(huì)對(duì)參數(shù)賦值。而參數(shù)傳遞過程其實(shí)同樣是變量復(fù)制的過程,所以它是按值傳遞。var person = person,因?yàn)閭鬟f參數(shù)是對(duì)象時(shí),變量復(fù)制僅復(fù)制的棧存儲(chǔ)(淺拷貝),所以修改對(duì)象屬性會(huì)造成外部變量對(duì)象的修改。

至此,當(dāng)我們理清棧、堆數(shù)據(jù)結(jié)構(gòu),以及JS中數(shù)據(jù)類型存取方式。深淺拷貝問題也就通順了。

內(nèi)存空間管理

JavaScript執(zhí)行過程中內(nèi)存分配:

為變量對(duì)象分配需要的內(nèi)存

在分配到的內(nèi)存中進(jìn)行讀/寫操作

不再使用時(shí)將其銷毀,釋放內(nèi)存

內(nèi)存管理不善,會(huì)出現(xiàn)內(nèi)存泄露,造成瀏覽器內(nèi)存占用過多,頁面卡頓等問題。(后續(xù)性能優(yōu)化篇章續(xù)講)

垃圾回收機(jī)制

JavaScript中有自動(dòng)垃圾回收機(jī)制,會(huì)通過標(biāo)記清除的算法識(shí)別哪些變量對(duì)象不再使用,對(duì)其進(jìn)行銷毀。開發(fā)者也可在代碼中手動(dòng)設(shè)置變量值為null(a = null)進(jìn)行標(biāo)記清除,讓其失去引用,以便下一次垃圾回收時(shí)進(jìn)行有效回收。

局部環(huán)境中,函數(shù)執(zhí)行完成后,函數(shù)局部環(huán)境聲明的變量不再需要時(shí),就會(huì)被垃圾回收銷毀(理想的情況下,閉包會(huì)阻止這一過程)。

全局環(huán)境只有頁面退出時(shí)才會(huì)出棧,解除變量引用。所以開發(fā)者應(yīng)盡量避免在全局環(huán)境中創(chuàng)建全局變量,如需使用,也要在不需要時(shí)手動(dòng)標(biāo)記清除,將其內(nèi)存釋放掉。

垃圾回收算法除了"標(biāo)記清除",還有一種"引用計(jì)數(shù)",不常用,僅作了解。

參考文檔:

stack的三種含義

內(nèi)存空間詳細(xì)圖解

JavaScript變量——棧內(nèi)存or堆內(nèi)存

本文首發(fā)Github,期待Star!
https://github.com/ZengLingYong/blog

作者:以樂之名
本文原創(chuàng),有不當(dāng)?shù)牡胤綒g迎指出。轉(zhuǎn)載請(qǐng)指明出處。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/101048.html

相關(guān)文章

  • 進(jìn)擊 JavaScript() 之 數(shù)據(jù)結(jié)構(gòu)

    摘要:的垃圾回收器,進(jìn)行回收。它們的數(shù)據(jù)就存放在堆內(nèi)存中,大小不一定,動(dòng)態(tài)分配內(nèi)存,可隨時(shí)修改。引用類型的變量存的是其在堆內(nèi)存中的地址,值的讀取,就是讀取這個(gè)內(nèi)存地址中儲(chǔ)存的內(nèi)容。 這東西還是很重要的,你要是搞懂了,就會(huì)去除很多困惑,比如不知道大家在學(xué)習(xí)js 的時(shí)候,有沒有對(duì) 基礎(chǔ)類型 和 引用類型 感到困惑過,兩者之間 表現(xiàn)的不同之處。 js 不同其他編程語言,它是腳本語言。所以,它的數(shù)...

    BlackFlagBin 評(píng)論0 收藏0
  • 前端進(jìn)擊巨人(一):執(zhí)行上下文與執(zhí)行,變量對(duì)象

    摘要:在中,通過棧的存取方式來管理執(zhí)行上下文,我們可稱其為執(zhí)行棧,或函數(shù)調(diào)用棧。而處于棧頂?shù)氖钱?dāng)前正在執(zhí)行函數(shù)的執(zhí)行上下文,當(dāng)函數(shù)調(diào)用完成后,它就會(huì)從棧頂被推出理想的情況下,閉包會(huì)阻止該操作,閉包后續(xù)文章深入詳解。 寫在開篇 已經(jīng)不敢自稱前端小白,曾經(jīng)吹過的牛逼總要一點(diǎn)點(diǎn)去實(shí)現(xiàn)。 正如前領(lǐng)導(dǎo)說的,自己喝酒吹過的牛皮,跪著都得含著淚去實(shí)現(xiàn)。 那么沒有年終完美總結(jié),來個(gè)新年莽撞開始可好。 進(jìn)擊巨...

    _Suqin 評(píng)論0 收藏0
  • 前端進(jìn)擊巨人(三):從作用域走進(jìn)閉包

    摘要:進(jìn)擊的巨人第三篇,本篇就作用域作用域鏈閉包等知識(shí)點(diǎn),一一擊破。在此我們遵照的方式,暫且稱是閉包。所以,一名合格的前端,除了會(huì)用閉包,還要正確的解除閉包引用。 進(jìn)擊的巨人第三篇,本篇就作用域、作用域鏈、閉包等知識(shí)點(diǎn),一一擊破。 showImg(https://segmentfault.com/img/bVburWd?w=1280&h=854); 作用域 作用域:負(fù)責(zé)收集并維護(hù)由所有聲明的...

    Vicky 評(píng)論0 收藏0
  • 前端進(jìn)擊巨人(六):知否知否,須知this

    摘要:有關(guān)函數(shù)柯里化的詳解,請(qǐng)回閱前端進(jìn)擊的巨人五學(xué)會(huì)函數(shù)柯里化。構(gòu)造函數(shù)中的通過操作符可以實(shí)現(xiàn)對(duì)函數(shù)的構(gòu)造調(diào)用。在了解構(gòu)造函數(shù)中的前,有必要先了解下實(shí)例化對(duì)象的過程。 showImg(https://segmentfault.com/img/bVburMp?w=800&h=600); 常見this的誤解 指向函數(shù)自身(源于this英文意思的誤解) 指向函數(shù)的詞法作用域(部分情況) th...

    Andrman 評(píng)論0 收藏0
  • 前端進(jìn)擊巨人(八):淺談函數(shù)防抖與節(jié)流

    摘要:隆重請(qǐng)出主角防抖與節(jié)流。防抖與節(jié)流的異同相同都是防止某一時(shí)間段內(nèi),函數(shù)被頻繁調(diào)用執(zhí)行,通過時(shí)間頻率控制,減少回調(diào)函數(shù)執(zhí)行次數(shù),來實(shí)現(xiàn)相關(guān)性能優(yōu)化。參考文章分鐘理解的節(jié)流防抖及使用場景函數(shù)防抖和節(jié)流 showImg(https://segmentfault.com/img/bVburM8?w=800&h=600); 本篇課題,或許早已是爛大街的解讀文章。不過春招系列面試下來,不少伙伴們還...

    _Zhao 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<