javascript中基本類型和引用類型的區(qū)別分析
基本類型和引用類型
ECMAScript包含兩個(gè)不同類型的值:基本類型值和引用類型值?;绢愋椭抵傅氖呛唵蔚臄?shù)據(jù)段;引用類型值指由多個(gè)值構(gòu)成的對象。當(dāng)我們把變量賦值給一個(gè)變量時(shí),解析器首先要做的就是確認(rèn)這個(gè)值是基本類型值還是引用類型值。
常見的五種基本數(shù)據(jù)類型是:
Undifined、Null、Boolean、Number和String。這五種基本數(shù)據(jù)類型可以直接操作保存在變量中的實(shí)際值。
看下面例子:
var a = 10; var b = a; b = 20; console.log(a); // 10 var bl = true; var bl1 = bl; bl1 = false; console.log(bl); // true
上面,b獲取值是a值的一份拷貝,雖然,兩個(gè)變量的值是相等,但是兩個(gè)變量保存兩不同的基本數(shù)據(jù)類型值。b只是保存了a復(fù)制的一個(gè)副本。所以,當(dāng)b的值改變時(shí),a的值依然是10;
下面,兩個(gè)Boolean變量bl和bl1同樣是基本數(shù)據(jù)類型,同樣保存兩個(gè)不同的基本數(shù)據(jù)據(jù)類型值,bl1保存bl復(fù)制的一個(gè)副本。
下圖演示了這種基本數(shù)據(jù)類型賦值的過程:
下面看一下引用類型數(shù)據(jù):
javascript引用數(shù)據(jù)類型是保存在堆內(nèi)存中的對象,與其它語言不同的是,你不可以直接訪問堆內(nèi)存空間中的位置和操作堆內(nèi)存空間。只能通過操作對象的在棧內(nèi)存中的引用地址。所以引用類型的數(shù)據(jù),在棧內(nèi)存中保存的實(shí)際上是對象在堆內(nèi)存中的引用地址。通過這個(gè)引用地址可以快速查找到保存在堆內(nèi)存中的對象。
看下下面的例子:
var obj1 = new Object(); var obj2 = obj1; obj2.name = "我有名字了"; console.log(obj1.name); // 我有名字了
由上面例子,我們聲明了一個(gè)引用數(shù)據(jù)類型變量obj1,并把它賦值給了另外一個(gè)引用數(shù)據(jù)類型變量obj2。當(dāng)我們obj2添加了一個(gè)name屬性并賦值"我有名字了"。obj1同樣擁有了和obj2一樣的name屬性。說明這兩個(gè)引用數(shù)據(jù)類型變量指向同一個(gè)堆內(nèi)存對象。obj1賦值給obj2,實(shí)際只是把這個(gè)堆內(nèi)存對象在棧內(nèi)存的引用地址復(fù)制了一份給了obj2,但它們本質(zhì)上共同指向了同一個(gè)堆內(nèi)存對象。
下面我們來演示這個(gè)引用數(shù)據(jù)類型賦值過程:
自然,給obj2添加name屬性,實(shí)際上是給堆內(nèi)存中的對象添加了name屬性,obj2和obj1在棧內(nèi)存中保存的只是堆內(nèi)存對象的引用地址,雖然也是拷貝了一份,但指向的對象卻是同一個(gè)。故而改變obj2引起了obj1的改變。
一般而言,基本數(shù)據(jù)類型是有固定數(shù)目的字節(jié)組成,這些字節(jié)可以在解析器的較底層進(jìn)行操作比如Number和Boolean;而引用數(shù)據(jù)類型,可以包含任意數(shù)目的屬性和元素,因此它們無法像基本數(shù)據(jù)類型那樣很容易的操作。由于,引用數(shù)據(jù)類型的值是會(huì)發(fā)生變化的,所以通過跟基本數(shù)據(jù)類型一樣的值傳遞方式,也就沒什么意義了,因?yàn)闀?huì)牽涉到大量的內(nèi)存的復(fù)制和比較,效率太低。所以引用數(shù)據(jù)類型是通過引用傳遞方式,實(shí)際傳遞的只是對象的一個(gè)地址。比如Array和Function因?yàn)樗鼈兌际翘厥獾膶ο笏运际且妙愋汀A硗?,引用類型是可以添加屬性,基本類型雖然也可以添加屬性,也不會(huì)報(bào)錯(cuò),經(jīng)測試添加完之后卻是無法訪問的。
看下面代碼:
var a = 12; a.name = "myname"; console.log(a.name); // undefined
String一個(gè)特殊的基本數(shù)據(jù)類型
在很多語言中,String是以對象的形式表示的,但在ECMAScript里沒有沿用這種傳統(tǒng),String是當(dāng)作一種基本數(shù)據(jù)類型,但它是一個(gè)比較特殊的基本類型。
看上去好像String應(yīng)該做為一個(gè)引用類型,可實(shí)際上它不是,因?yàn)樗皇菍ο?。那么看起來它?yīng)該是基本數(shù)據(jù)類型,應(yīng)該是通值傳遞的方式來操作。
看下面例子:
var stra = "這是一個(gè)字符串"; var strb = stra; stra = "這是另外一個(gè)字符串"; console.log(strb); // 這是一個(gè)字符串
上面例子我們看到,仿佛stra通過值傳遞的方式復(fù)制了一份給了strb。當(dāng)stra改變的時(shí)候,strb并沒有改變,似乎我們已經(jīng)可以下結(jié)論,String就是個(gè)基本數(shù)據(jù)類型。
可是,因?yàn)镾tring是可以任意長度的,通過值傳遞,一個(gè)一個(gè)的復(fù)制字節(jié)顯示效率依然很低,看起來String也可以當(dāng)作引用類型。
看下面例子:
var a = "myobject"; a.name = "myname"; console.log(a.name); // undefined
顯示String無法當(dāng)作一個(gè)對象來處理。實(shí)際上,javascript里的String是不可以改變的,javascript也沒有提供任何一個(gè)改變字符串的方法和語法。
var a = "myobject"; a = a.substring(3,5) console.log(a); // bj
記住這樣做,就沒有改變String字符串"myobject",只a引用了另一個(gè)字符串"bj","myobject"被回收了。
所以可以這樣講,String實(shí)際上并不符合上面兩種數(shù)據(jù)類型分類。它是具有兩方面屬性介于兩都之間的一種特殊類型。
以上所述就是本文的全部內(nèi)容了,希望大家能夠喜歡。
相關(guān)文章
JavaScript實(shí)現(xiàn)微信號(hào)隨機(jī)切換代碼
這篇文章主要介紹了JavaScript實(shí)現(xiàn)微信號(hào)隨機(jī)切換代碼,需要的朋友可以參考下2018-03-03JavaScript實(shí)現(xiàn)隨機(jī)點(diǎn)名器實(shí)例詳解
這篇文章主要介紹了JavaScript隨機(jī)點(diǎn)名器,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05ES6擴(kuò)展運(yùn)算符和rest運(yùn)算符用法實(shí)例分析
這篇文章主要介紹了ES6擴(kuò)展運(yùn)算符和rest運(yùn)算符用法,結(jié)合實(shí)例形式分析了ES6擴(kuò)展運(yùn)算符和rest運(yùn)算符基本功能、用法及操作注意事項(xiàng),需要的朋友可以參考下2020-05-0567 個(gè)節(jié)約開發(fā)時(shí)間的前端開發(fā)者的工具、庫和資源
在本文中,我不會(huì)去談 React、Angular、Vue 等等這些大的前端框架,也不會(huì)談 Atom、VS code、Sublime 等等這些已經(jīng)很出名的代碼編輯器,我只是想簡單的分享一套我認(rèn)為有助于提升開發(fā)者工作流的工具集2017-09-09簡易版本JSON.stringify的實(shí)現(xiàn)及其六大特性詳解
最近做項(xiàng)目發(fā)現(xiàn)JSON.stringify()使用場景真的挺多,我們都知道JSON.stringify()的作用是將JavaScript對象轉(zhuǎn)換為JSON字符串,下面這篇文章主要給大家介紹了JSON.stringify的實(shí)現(xiàn)及其六大特性的相關(guān)資料,需要的朋友可以參考下2021-10-10es7學(xué)習(xí)教程之fetch解決異步嵌套問題的方法示例
這篇文章主要給大家介紹了關(guān)于es7學(xué)習(xí)教程之fetch解決異步嵌套問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。2017-07-07