object,你的腰間盤為啥這么突出案训?——數(shù)據(jù)類型轉(zhuǎn)換中object的不同之處及原因探究

突出.jpg

在我的上一篇文章中JavaScript的家族譜(數(shù)據(jù)類型)已經(jīng)介紹了關(guān)于object和普通類型在數(shù)據(jù)類型呈現(xiàn)方式上的不同买置,object是復(fù)雜類型,不同于其他基本類型的不可再分割强霎,object內(nèi)部可能有函數(shù)忿项、數(shù)組和其他數(shù)據(jù)類型混合其中。而本文將從另外一個(gè)角度——儲存方式來闡述object的特殊之處城舞。(注意本文不談symbol)

數(shù)據(jù)類型之間的相互轉(zhuǎn)化

為什么要先談這個(gè)轩触,因?yàn)榛绢愋秃蛷?fù)雜類型(object)的存儲方式并不一樣,在數(shù)據(jù)轉(zhuǎn)化過程中這個(gè)事實(shí)最為明顯家夺。

其他基本類型轉(zhuǎn)化為String(特別注意object)

方式一 :原始數(shù)據(jù).toString()

var a = 1
a.toString()
"1" //數(shù)值轉(zhuǎn)化為字符串

var a = true
a.toString()
"true" //布爾值轉(zhuǎn)化為字符串

var a = null
a.toString()
VM426:1 Uncaught TypeError: Cannot read property 'toString' of null
    at <anonymous>:1:3 
//null不能直接轉(zhuǎn)化為字符串怕膛,因?yàn)閚ull沒有toString這個(gè)屬性

var a = undefined
undefined
a.toString()
VM446:1 Uncaught TypeError: Cannot read property 'toString' of undefined
    at <anonymous>:1:3
(anonymous) @ VM446:1
// 同理undefined也沒有

var a = {}
undefined
typeof a
"object"
a.toString()
"[object Object]"
// 突出1:要么就老老實(shí)實(shí)轉(zhuǎn)化,要么就像null一樣說沒有不就好了秦踪,給個(gè)奇怪的返回值

方式二:String(原始數(shù)據(jù))

var a = 1
String(a)
"1"
//剩下的就省略了褐捻,結(jié)果和上面的相同

方式三:原始數(shù)據(jù) + "
這種方式并不是調(diào)用屬性,而是讓原始數(shù)據(jù)匹配字符串椅邓,所以null和undefined也是可以轉(zhuǎn)化的

a + ''
"1"

null+''
"null" 

undefined+''
"undefined"

var a = {key:1}
undefined
a+""
"[object Object]" //行柠逞,你NB

其他類型轉(zhuǎn)化為布爾值

五個(gè)falsy值

這里說一下,所有數(shù)據(jù)類型轉(zhuǎn)化成布爾值景馁,其中只有5個(gè)會被轉(zhuǎn)化為false:

  1. 0
  2. NaN
  3. ''(空字符串)
  4. null
  5. undefined

方法

方法一:Boolean(原始數(shù)據(jù))

Boolean(a)
true
Boolean(0)
false
Boolean(NaN)
false
Boolean('')
false
Boolean(null)
false
Boolean(undefined)
false
Boolean({})
true // 突出2:object啥也沒有也是true

方法二:0遄场!原始數(shù)據(jù)(合住!是取反的意思)

!!1
true
!!null
false
// 其他的就不舉例了

其他類型轉(zhuǎn)化成數(shù)值(這個(gè)不突出绰精,主要是有NaN背鍋)

方法

方法一:Number(原始值)

var a = {key :'1'}
typeof a
"object"
Number(a)
NaN
Number('1')
1
Number('1sss')
NaN //這個(gè)方法只要字符串中有非數(shù)字的就返回NaN
Number(true)
1 //后面從儲存的角度來解釋
Number(false)
0  //后面從儲存的角度來解釋
Number(null)
0
Number(undefined)
NaN

方法二:parseInt(原始值,'進(jìn)制數(shù)')--注意是十進(jìn)制時(shí)可以不寫透葛,系統(tǒng)默認(rèn)是存在的
這個(gè)方法和上面不同之處在于這個(gè)命令只取整笨使,除了數(shù)值和能轉(zhuǎn)化的字符串,其他的全是NaN僚害。另外,他能提取字符串前面的數(shù)字硫椰,具體用法見parseInt

parseInt('1sss')
1 //

方法三:parseFloat('原始值'),具體用法見parseFloat

方法四(簡單寫法):原始數(shù)據(jù) - 0
方法五(更簡單寫法):+ 原始數(shù)據(jù)

true -0
1
'a' -0
NaN
+ true
1
+'a' 
NaN

(symbol轉(zhuǎn)化我們就不談及,至于怎么轉(zhuǎn)化成null或者undefined萨蚕,請把你的需求寫在評論區(qū)靶草,讓大家一起來深入探討)

那么其他數(shù)據(jù)類型轉(zhuǎn)化成對象怎么做?

答案是:obeject(原始值)

var a =1
typeof(a)
"number"
b = Object(a)
typeof b
"object" //給值一個(gè)對象包裹器

討論(開始閑扯)

現(xiàn)在我們來回顧一下上面所有的轉(zhuǎn)化過程岳遥,只從數(shù)據(jù)的展現(xiàn)形式什么也看不出來奕翔。這時(shí)候我們只能從數(shù)據(jù)的儲存方式來看看。

簡單的存儲模型

JS有兩個(gè)儲存數(shù)據(jù)的區(qū)域(Stack和Heap)浩蓉,基本數(shù)據(jù)類型幾乎全部存放在Stack里面派继,如此我們假設(shè)一個(gè)簡單模型 stack里面保存數(shù)據(jù)都是用哈希表的方式保存(key:value)帮坚,Heap保存數(shù)據(jù)的方式是堆(無序存放,只有地址)互艾。--比實(shí)際情況簡單便于理解

  1. 模型中基本類型數(shù)據(jù)的儲存方式(注意所有的數(shù)據(jù)都是用二進(jìn)制表示)
    布爾值(booleantrue保存的時(shí)候就是1试和,false就是0
    字符串(String)把引號內(nèi)部的內(nèi)容用utf-16保存纫普,單雙引號就是單雙引號阅悍,前后各一個(gè)表示開頭結(jié)尾(真實(shí)情況并非如此);
    數(shù)值(number)用二進(jìn)制表示昨稼;
    null:null用二進(jìn)制表示节视;
    undefined:undefined用二進(jìn)制表示;
    以上全部保存在Stack里面

  2. 模型中復(fù)雜類型數(shù)據(jù)(object)的儲存方式(突出3:存的地方有兩個(gè))
    object保存在Stack里面的是object Object(二進(jìn)制表示) +地址(二進(jìn)制表示)假栓,Heap保存的是這個(gè)地址引用的數(shù)據(jù)寻行,也就是object里面的內(nèi)容。

  3. String等命令只在Stack里面尋找數(shù)據(jù)匾荆。

推演

  1. 基本類型之間轉(zhuǎn)化在儲存的角度上的事件(簡單模型中)
    那么所有的基本類型的轉(zhuǎn)化拌蜘,只需要把他原始的數(shù)據(jù)修改或者全部刪除然后寫入,讀取的時(shí)候把要讀取的部分取出來就可以了牙丽。

  2. object在上文中的突出點(diǎn)的解讀
    突出1:為什么字符串轉(zhuǎn)化是"[object Object]"

var a = {}
undefined
typeof a
"object"
a.toString()
"[object Object]"

看看我們的對象在Stack里面是怎么保存的:object Object(二進(jìn)制表示) +地址(二進(jìn)制表示)简卧。字符串沒有解讀地址而已,而每一個(gè)對象都是這個(gè)格式保存著烤芦。這個(gè)模型也就解釋了突出2:空的對象轉(zhuǎn)成布爾值也是true举娩,因?yàn)槔锩鎸懼?code>object Object,不是5個(gè)Falsy值构罗,返回true铜涉。至于地址有沒有,對不起遂唧,布爾值無法解讀芙代。

  1. 綜上看,實(shí)際上object和其他數(shù)據(jù)類型轉(zhuǎn)化這涉及到了儲存數(shù)據(jù)方式的變化

拓展--深拷貝和淺拷貝

深拷貝就是我變你也不變蠢箩,淺拷貝就是我變你也變
用上面這個(gè)簡單模型可以很好地解決深淺拷貝的問題
例如

var a = {name:'a'}
var b = a
b.name = 'b'
// a = ?

模型分析:

  1. Stack存儲著哈希表a:object Object 地址1
  2. Heap里面存儲著堆數(shù)據(jù):地址1{name:'a'}
  3. b = a 使又增加一個(gè)哈希表b:object Object 地址1链蕊,這時(shí)b變量也是引用地址1
  4. b.name(這是object的命令)調(diào)用地址1里面的屬性name,讓name:'a'變成name:'b'谬泌,此時(shí)Heap里的地址1變成地址1{name:'b'}
  5. 然后問a,a的stack并沒有變化a:object Object 地址1逻谦,而引用的地址1數(shù)據(jù)是地址1{name:'b'}掌实,所以a = 'b'。這就是淺拷貝邦马,你變我也變贱鼻。變的原因在于地址里的內(nèi)容變了宴卖。

再舉一個(gè)深拷貝的例子

var a = 1
var b = a
b = 2
// a = ?

模型分析:

  1. Stack存儲著哈希表a:1
  2. b = a使Stack中又多出一個(gè)哈希表b:1
  3. b = 2使Stack中b的value由1變成2,哈希表為b:2
  4. 問a是多少邻悬,哈希表a:1并沒有變化症昏,所以a=1。這就是深拷貝父丰,你變我不變肝谭。

由這兩個(gè)例子可以看出,只涉及Stack的數(shù)據(jù)變化并不會發(fā)生淺拷貝蛾扇,所以基本類型的拷貝全是深拷貝

文末要謝謝方方老師精彩的知識講解攘烛,這篇文章中大部分知識借鑒方方老師的知識,另外因?yàn)閮?nèi)存圖是方方老師原創(chuàng)镀首,而且簡書不能加動(dòng)態(tài)圖坟漱,所以這里使用了簡單模型代替,如有錯(cuò)誤歡迎指正更哄。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末芋齿,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子成翩,更是在濱河造成了極大的恐慌沟突,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捕传,死亡現(xiàn)場離奇詭異惠拭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)庸论,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進(jìn)店門职辅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人聂示,你說我怎么就攤上這事域携。” “怎么了鱼喉?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵秀鞭,是天一觀的道長。 經(jīng)常有香客問我扛禽,道長锋边,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任编曼,我火速辦了婚禮豆巨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘掐场。我一直安慰自己往扔,他們只是感情好贩猎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著萍膛,像睡著了一般吭服。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蝗罗,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天艇棕,我揣著相機(jī)與錄音,去河邊找鬼绿饵。 笑死欠肾,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拟赊。 我是一名探鬼主播刺桃,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吸祟!你這毒婦竟也來了瑟慈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤屋匕,失蹤者是張志新(化名)和其女友劉穎葛碧,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體过吻,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡进泼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纤虽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乳绕。...
    茶點(diǎn)故事閱讀 40,110評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖逼纸,靈堂內(nèi)的尸體忽然破棺而出洋措,到底是詐尸還是另有隱情,我是刑警寧澤杰刽,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布菠发,位于F島的核電站,受9級特大地震影響贺嫂,放射性物質(zhì)發(fā)生泄漏滓鸠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一涝婉、第九天 我趴在偏房一處隱蔽的房頂上張望哥力。 院中可真熱鬧,春花似錦墩弯、人聲如沸吩跋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锌钮。三九已至,卻和暖如春引矩,著一層夾襖步出監(jiān)牢的瞬間梁丘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工旺韭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留氛谜,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓区端,卻偏偏與公主長得像值漫,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子织盼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內(nèi)容