js中的數(shù)據(jù)類型
==基本類型==:Number Boolean Undefined String Null Symbol
==引用類型==:Object Function Array Data
基本類型的數(shù)據(jù)是存放在棧內存中的逊脯,而引用類型的數(shù)據(jù)是存放在堆內存中的。
基本類型的復制就是在棧內存中開辟出了一個新的存儲區(qū)域用來存儲新的變量锥累,這個變量有它自己的值谎僻,只不過和前面的值一樣,所以如果其中一個值的改變,則不會影響另一個茄茁。
引用類型的復制其實是在棧內存中存儲了一個指針,這個指針指向堆內存中該對象的存儲地址巩割,復制給另一個對象的過程其實就是把該對象的地址復制給了另一個對象變量裙顽,兩個指針都指向同一個對象,所以其中一個修改了宣谈,則另一個也會改變愈犹。
基本類型沒有方法和屬性,因為一旦創(chuàng)建了屬性或者方法就會被立刻銷毀闻丑,但是由于js中的變量是松散類型的漩怎,所以它提供了一種檢測當前變量的數(shù)據(jù)類型的方法,也就是typeof關鍵字嗦嗡,通過typeof關鍵字勋锤,對基本數(shù)據(jù)類型回返回下面的值(以字符串形式顯示)
undefined => undefined
boolean => boolean
string => string
number => number
null => object (因為特殊值null被認為是一個空的對象引用)
==總結區(qū)別==
==a 聲明變量時不同的內存分配:==
1)原始值:存儲在棧(stack)中的簡單數(shù)據(jù)段,也就是說侥祭,它們的值直接存儲在變量訪問的位置叁执。
這是因為這些原始類型占據(jù)的空間是固定的茄厘,所以可將他們存儲在較小的內存區(qū)域 – 棧中。這樣存儲便于迅速查尋變量的值谈宛。
2)引用值:存儲在堆(heap)中的對象次哈,也就是說,存儲在變量處的值是一個指針(point)吆录,指向存儲對象的內存地址亿乳。
這是因為:引用值的大小會改變,所以不能把它放在棧中径筏,否則會降低變量查尋的速度。相反障陶,放在變量的椬烫瘢空間中的值是該對象存儲在堆中的地址。
地址的大小是固定的抱究,所以把它存儲在棧中對變量性能無任何負面影響恢氯。
==b 不同的內存分配機制也帶來了不同的訪問機制==
1)在javascript中是不允許直接訪問保存在堆內存中的對象的,所以在訪問一個對象時鼓寺,首先得到的是這個對象在堆內存中的地址勋拟,然后再按照這個地址去獲得這個對象中的值,這就是傳說中的按引用訪問妈候。
2)而原始類型的值則是可以直接訪問到的敢靡。
==c 復制變量時的不同==
1)原始值:在將一個保存著原始值的變量復制給另一個變量時,會將原始值的副本賦值給新變量苦银,此后這兩個變量是完全獨立的啸胧,他們只是擁有相同的value而已。
2)引用值:在將一個保存著對象內存地址的變量復制給另一個變量時幔虏,會把這個內存地址賦值給新變量纺念,也就是說這兩個變量都指向了堆內存中的同一個對象,他們中任何一個作出的改變都會反映在另一個身上想括。(這里要理解的一點就是陷谱,復制對象時并不會在堆內存中新生成一個一模一樣的對象,只是多了一個保存指向這個對象指針的變量罷了)多了一個指針瑟蜈。
==d 參數(shù)傳遞的不同(把實參復制給形參的過程)==
首先我們應該明確一點:ECMAScript中所有函數(shù)的參數(shù)都是按值來傳遞的烟逊。但是為什么涉及到原始類型與引用類型的值時仍然有區(qū)別呢?還不就是因為內存分配時的差別踪栋。
1)原始值:只是把變量里的值傳遞給參數(shù)焙格,之后參數(shù)和這個變量互不影響。
2)引用值:對象變量它里面的值是這個對象在堆內存中的內存地址夷都,這一點你要時刻銘記在心眷唉!
因此它傳遞的值也就是這個內存地址予颤,這也就是為什么函數(shù)內部對這個參數(shù)的修改會體現(xiàn)在外部的原因了,因為它們都指向同一個對象冬阳。
==Symbol==
symbol 通過Symbol函數(shù)生成
let s = Symbol();
typeof s //symbol
這就是說蛤虐,對象的屬性名現(xiàn)在可以有兩種類型,一種是原來就有的字符串肝陪,另一種就是新增的 Symbol 類型驳庭。凡是屬性名屬于 Symbol 類型,就都是獨一無二的氯窍,可以保證不會與其他屬性名產生沖突饲常。
==注意==:Symbol函數(shù)前不能使用new命令,否則會報錯狼讨。這是因為生成的 Symbol 是一個原始類型的值贝淤,不是對象。也就是說政供,由于 Symbol 值不是對象播聪,所以不能添加屬性〔几簦基本上离陶,它是一種類似于字符串的數(shù)據(jù)類型。