JavaScript基礎(chǔ)心法 數(shù)據(jù)類型
由于自己是野生程序員,在剛開始學(xué)習(xí)程序設(shè)計(jì)的時(shí)候沒有在意內(nèi)存這些基礎(chǔ)知識(shí),導(dǎo)致后來在提到“什么什么是存在棧中的,棧中只是存了一個(gè)引用”這樣的話時(shí)總是一臉懵逼。。
后來漸漸的了解了一些內(nèi)存的知識(shí),這部分還是非常有必要了解的。
基本數(shù)據(jù)結(jié)構(gòu)
棧
棧,只允許在一段進(jìn)行插入或者刪除操作的線性表,是一種先進(jìn)后出的數(shù)據(jù)結(jié)構(gòu)。
堆
堆是基于散列算法的數(shù)據(jù)結(jié)構(gòu)。
隊(duì)列
隊(duì)列是一種先進(jìn)先出(FIFO)的數(shù)據(jù)結(jié)構(gòu)。
JavaScript中數(shù)據(jù)類型的存儲(chǔ)
JavaScript中將數(shù)據(jù)類型分為基本數(shù)據(jù)類型和引用數(shù)據(jù)類型,它們其中有一個(gè)區(qū)別就是存儲(chǔ)的位置不同。
基本數(shù)據(jù)類型
我們都知道JavaScript中的基本數(shù)據(jù)類型有:
- String
- Number
- Boolean
- Undefined
- Null
- Symbol(暫時(shí)不管)
基本數(shù)據(jù)類型都是一些簡(jiǎn)單的數(shù)據(jù)段,它們是存儲(chǔ)在棧內(nèi)存中。
引用數(shù)據(jù)類型
JavaScript中的引用數(shù)據(jù)類型有:
- Array
- Object
引用數(shù)據(jù)類型是保存在堆內(nèi)存中的,然后再棧內(nèi)存中保存一個(gè)對(duì)堆內(nèi)存中實(shí)際對(duì)象的引用。所以,JavaScript中對(duì)引用數(shù)據(jù)類型的操作都是操作對(duì)象的引用而不是實(shí)際的對(duì)象。
可以理解為,棧內(nèi)存中保存了一個(gè)地址,這個(gè)地址和堆內(nèi)存中的實(shí)際值是相關(guān)的。
圖解
現(xiàn)在,我們聲明幾個(gè)變量試試:
var name="axuebin"; var age=25; var job; var arr=[1,2,3]; var obj={age:25};
可以通過下圖來表示數(shù)據(jù)類型在內(nèi)存中的存儲(chǔ)情況:
此時(shí)name
,age
,job
三種基本數(shù)據(jù)類型是直接存在棧內(nèi)存中的,而arr,obj在棧內(nèi)存中只是存了一個(gè)地址來表示對(duì)堆內(nèi)存中的引用。
復(fù)制
基本數(shù)據(jù)類型
對(duì)于基本數(shù)據(jù)類型,如果進(jìn)行復(fù)制,系統(tǒng)會(huì)自動(dòng)為新的變量在棧內(nèi)存中分配一個(gè)新值,很容易理解。
引用數(shù)據(jù)類型
如果對(duì)于數(shù)組、對(duì)象這樣的引用數(shù)據(jù)類型而言,復(fù)制的時(shí)候就會(huì)有所區(qū)別了:
系統(tǒng)也會(huì)自動(dòng)為新的變量在棧內(nèi)存中分配一個(gè)值,但這個(gè)值僅僅是一個(gè)地址。也就是說,復(fù)制出來的變量和原有的變量具有相同的地址值,指向堆內(nèi)存中的同一個(gè)對(duì)象。
如果所示,執(zhí)行了var objCopy=obj之后,obj和objCopy具有相同的地址值,執(zhí)行堆內(nèi)存中的同一個(gè)實(shí)際對(duì)象。
這有什么不同呢?
當(dāng)我修改obj或objCopy時(shí),都會(huì)引起另一個(gè)變量的改變。
為什么?
為什么基礎(chǔ)數(shù)據(jù)類型存在棧中,而引用數(shù)據(jù)類型存在堆中呢?
- 堆比棧大,棧比對(duì)速度快。
- 基礎(chǔ)數(shù)據(jù)類型比較穩(wěn)定,而且相對(duì)來說占用的內(nèi)存小。
- 引用數(shù)據(jù)類型大小是動(dòng)態(tài)的,而且是無限的。
- 堆內(nèi)存是無序存儲(chǔ),可以根據(jù)引用直接獲取。
參考文章
理解js內(nèi)存分配
原始值和引用值
在ECMAScript中,變量可以存放兩種類型的值,即原始值和引用值。
原始值指的就是代表原始數(shù)據(jù)類型(基本數(shù)據(jù)類型)的值,即Undefined,Null,Number,String,Boolean類型所表示的值。
引用值指的就是復(fù)合數(shù)據(jù)類型的值,即Object,Function,Array,以及自定義對(duì)象,等等
棧和堆
與原始值與引用值對(duì)應(yīng)存在兩種結(jié)構(gòu)的內(nèi)存即棧和堆
棧是一種后進(jìn)先出的數(shù)據(jù)結(jié)構(gòu),在javascript中可以通過Array來模擬棧的行為
原始值是存儲(chǔ)在棧中的簡(jiǎn)單數(shù)據(jù),也就是說,他們的值直接存儲(chǔ)在變量訪問的位置。
堆是基于散列算法的數(shù)據(jù)結(jié)構(gòu),在javascript中,引用值是存放在堆中的。
引用值是存儲(chǔ)在堆中的對(duì)象,也就是說,存儲(chǔ)在變量處的值(即指向?qū)ο蟮淖兞?,存?chǔ)在棧中)是一個(gè)指針,指向存儲(chǔ)在堆中的實(shí)際對(duì)象.
例:var obj = new Object(); obj存儲(chǔ)在棧中它指向于new Object()這個(gè)對(duì)象,而new Object()是存放在堆中的。
那為什么引用值要放在堆中,而原始值要放在棧中,不都是在內(nèi)存中嗎,為什么不放在一起呢?那接下來,讓我們來探索問題的答案!
首先,我們來看一下代碼:
function Person(id,name,age){ this.id = id; this.name = name; this.age = age; } var num = 10; var bol = true; var str = "abc"; var obj = new Object(); var arr = ['a','b','c']; var person = new Person(100,"笨蛋的座右銘",25);
然后我們來看一下內(nèi)存分析圖:
變量num,bol,str為基本數(shù)據(jù)類型,它們的值,直接存放在棧中,obj,person,arr為復(fù)合數(shù)據(jù)類型,他們的引用變量存儲(chǔ)在棧中,指向于存儲(chǔ)在堆中的實(shí)際對(duì)象。
由上圖可知,我們無法直接操縱堆中的數(shù)據(jù),也就是說我們無法直接操縱對(duì)象,但我們可以通過棧中對(duì)對(duì)象的引用來操作對(duì)象,就像我們通過遙控機(jī)操作電視機(jī)一樣,區(qū)別在于這個(gè)電視機(jī)本身并沒有控制按鈕。
現(xiàn)在讓我們來回答為什么引用值要放在堆中,而原始值要放在棧中的問題:
記住一句話:能量是守衡的,無非是時(shí)間換空間,空間換時(shí)間的問題
堆比棧大,棧比堆的運(yùn)算速度快,對(duì)象是一個(gè)復(fù)雜的結(jié)構(gòu),并且可以自由擴(kuò)展,如:數(shù)組可以無限擴(kuò)充,對(duì)象可以自由添加屬性。將他們放在堆中是為了不影響棧的效率。而是通過引用的方式查找到堆中的實(shí)際對(duì)象再進(jìn)行操作。相對(duì)于簡(jiǎn)單數(shù)據(jù)類型而言,簡(jiǎn)單數(shù)據(jù)類型就比較穩(wěn)定,并且它只占據(jù)很小的內(nèi)存。不將簡(jiǎn)單數(shù)據(jù)類型放在堆是因?yàn)橥ㄟ^引用到堆中查找實(shí)際對(duì)象是要花費(fèi)時(shí)間的,而這個(gè)綜合成本遠(yuǎn)大于直接從棧中取得實(shí)際值的成本。所以簡(jiǎn)單數(shù)據(jù)類型的值直接存放在棧中。
- javascript數(shù)據(jù)類型基礎(chǔ)示例教程
- JavaScript基礎(chǔ)語(yǔ)法與數(shù)據(jù)類型介紹
- js中基礎(chǔ)的數(shù)據(jù)類型詳解
- javascript基礎(chǔ)之?dāng)?shù)據(jù)類型詳解
- JavaScript的基礎(chǔ)語(yǔ)法和數(shù)據(jù)類型詳解
- JavaScript 變量,數(shù)據(jù)類型基礎(chǔ)實(shí)例詳解【變量、字符串、數(shù)組、對(duì)象等】
- 淺談js基礎(chǔ)數(shù)據(jù)類型和引用類型,深淺拷貝問題,以及內(nèi)存分配問題
- Javascript基礎(chǔ)教程之?dāng)?shù)據(jù)類型轉(zhuǎn)換
- Javascript基礎(chǔ)教程之?dāng)?shù)據(jù)類型 (布爾型 Boolean)
- Javascript基礎(chǔ)教程之?dāng)?shù)據(jù)類型 (數(shù)值 Number)
- Javascript基礎(chǔ)教程之?dāng)?shù)據(jù)類型 (字符串 String)
- JavaScript基礎(chǔ)知識(shí)之?dāng)?shù)據(jù)類型
- javascript 基礎(chǔ)篇2 數(shù)據(jù)類型,語(yǔ)句,函數(shù)
- javascript基礎(chǔ)數(shù)據(jù)類型轉(zhuǎn)換教程示例
相關(guān)文章
javascript中對(duì)Date類型的常用操作小結(jié)
下面小編就為大家?guī)硪黄猨avascript中對(duì)Date類型的常用操作小結(jié)。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-05-05Knockout數(shù)組(observable)使用詳解示例
本文通過示例詳細(xì)說明了Knockout數(shù)組(observable)的使用方法,如從observableArray里讀取信息、操作observableArray2013-11-11<script defer> defer 是什么意思
好多朋友不知道 script后面加個(gè)defer是什么意思有什么作用。2009-05-05國(guó)內(nèi)常用的js類庫(kù)大全(CDN公共庫(kù))
羅列這類js類庫(kù)希望能幫助到大家,下面類庫(kù)都支持CDN,所以不用擔(dān)心速度問題,就算某個(gè)節(jié)點(diǎn)慢也不會(huì)影響全國(guó)其他地區(qū)的訪問速度,支持jQuery,Bootstrap,angular,zepto等js庫(kù)的CDN地址2020-06-06深入解析JavaScript中的立即執(zhí)行函數(shù)
立即執(zhí)行函數(shù)模式在JavaScript中可以讓你的函數(shù)在定義后立即被執(zhí)行,下面我們就來深入解析JavaScript中的立即執(zhí)行函數(shù),需要的朋友可以參考下2016-05-05javascript學(xué)習(xí)筆記(二)數(shù)組和對(duì)象部分
本文是學(xué)習(xí)筆記系列的第二篇,深入淺出的分別從javascript對(duì)象和數(shù)組兩個(gè)部分介紹了相關(guān)知識(shí),并附上詳細(xì)示例,非常的實(shí)用,有需要的朋友可以參考下2014-09-09一個(gè)簡(jiǎn)單的網(wǎng)站訪問JS計(jì)數(shù)器 刷新1次加1次訪問
一個(gè)簡(jiǎn)單的網(wǎng)站訪問JS計(jì)數(shù)器,一般就是學(xué)習(xí)下原來,不建議使用,現(xiàn)在cnzz或百度統(tǒng)計(jì)多試不錯(cuò)的2012-09-09javascript語(yǔ)言結(jié)構(gòu)小記(一)
今天看了點(diǎn)js語(yǔ)言結(jié)構(gòu)的一部分,我將我比較感興趣地記錄如下,想學(xué)習(xí)js的朋友可以看下。2011-09-09