1.JS有5種簡(jiǎn)單數(shù)據(jù)類型(也稱基本數(shù)據(jù)類型):undefined、null、Boolean、Number和String。還有兩種復(fù)雜數(shù)據(jù)類型——symbol(這里不做多介紹)和Object,對(duì)象本質(zhì)上是由一組無(wú)序的名值對(duì)組成的,ECMAScring不支持任何創(chuàng)建自定義類型的機(jī)制,而所有值最終都將是上述7種數(shù)據(jù)類型之一。
數(shù)據(jù)類型的相互轉(zhuǎn)換
1.任意數(shù)據(jù)類型轉(zhuǎn)字符串
String(x)
String(1)//"1"
String(true)//"true"
String(null)//"null"
String(undefined)//"undefined"
String({})//"[Object Object]"
toString()
(1).toString() //"1"
true.toString() //"true"
null.toString() //Uncaught TypeError: Cannot read property 'toString' of null
// at <anonymous>:1:6
undefined.toString() //Uncaught TypeError: Cannot read property 'toString' of undefined
//at <anonymous>:1:11
{}.toString() //Uncaught SyntaxError: Unexpected token .
({}).toString() //"[object Object]"
老司機(jī)用法:x+''
1+'' // "1"
true+'' // 'true'
null+'' // 'null'
undefined+'' // 'undefined'
{}+'' // 0
var o = {}
o+ '' //{object Object}
2.任意數(shù)據(jù)類型轉(zhuǎn)數(shù)字
1.Number(x)
2.parselnt(x,10)
MDN
3.parseFloat(x)
MDN
4.x-0
5.+x
3.任意數(shù)據(jù)類型轉(zhuǎn)布爾值
1.Boolean(x)
2.!!x
4.五個(gè)falsy值
0 NaN '' null undefined .
falsy是在Boolean上下文中認(rèn)定可轉(zhuǎn)換為false的值。
JavaScript在需要用到布爾類型的上下文中使用強(qiáng)制類型轉(zhuǎn)換(Type Conversion)將值轉(zhuǎn)換為布爾值,比如:在條件語(yǔ)句或循環(huán)語(yǔ)句中
5.內(nèi)存圖
- 你買一個(gè) 8G 的內(nèi)存條
- 操作系統(tǒng)開(kāi)機(jī)即占用 512MB
- Chrome 打開(kāi)即占用 1G 內(nèi)存
- Chrome 各每個(gè)網(wǎng)頁(yè)分配一定數(shù)量的內(nèi)存
- 這些內(nèi)存要分給頁(yè)面渲染器、網(wǎng)絡(luò)模塊、瀏覽器外殼和 JS 引擎(V8引擎)
- JS 引擎將內(nèi)存分為代碼區(qū)和數(shù)據(jù)區(qū)
- 我們只研究數(shù)據(jù)區(qū)
*數(shù)據(jù)區(qū)分為 Stack(棧內(nèi)存) 和 Heap(堆內(nèi)存) - 簡(jiǎn)單類型的數(shù)據(jù)直接存在 Stack 里
- 復(fù)雜類型的數(shù)據(jù)是把 Heap 地址存在 Stack 里
遇到問(wèn)題就畫圖,不要分析。
如果將復(fù)雜數(shù)據(jù)類型存放在棧內(nèi)存里面,那么向其中添加數(shù)據(jù)就很麻煩、一些數(shù)據(jù)就需要向后面移動(dòng)。只需要在棧內(nèi)存中給代表復(fù)雜數(shù)據(jù)類型(對(duì)象)的變量存放一個(gè)地址(沒(méi)有指針,是引用)指向堆內(nèi)存中的數(shù)據(jù)。一個(gè)變量等于另一個(gè)復(fù)雜數(shù)據(jù)類型,就把地址復(fù)制給它。
所有的變量和對(duì)象都是引用關(guān)系。
4個(gè)常見(jiàn)的面試題
var a = 1
var b = a
b = 2
請(qǐng)問(wèn) a 顯示是幾? //1
var a = {name: 'a'}
var b = a
b = {name: 'b'}
請(qǐng)問(wèn)現(xiàn)在 a.name 是多少?//'a'
var a = {name: 'a'}
var b = a
b.name = 'b'
請(qǐng)問(wèn)現(xiàn)在 a.name 是多少?//'b'
var a = {name: 'a'}
var b = a
b = null
請(qǐng)問(wèn)現(xiàn)在 a 是什么?//{name: 'a'}
垃圾回收機(jī)制
GC 垃圾回收 如果一個(gè)對(duì)象沒(méi)有被引用,那么它就是垃圾,將會(huì)被回收。
引用包括事件觸發(fā)引用,如果一個(gè)函數(shù)被頁(yè)面上的事件引用了,也不會(huì)算作垃圾被回收。
解決辦法:將事件賦值null,就表示不再引用。
IE6 BUG 無(wú)法正常的在頁(yè)面關(guān)閉時(shí),將沒(méi)有人引用的垃圾正常的清除。設(shè)置window.onunload事件,將所有的事件都設(shè)置為null。
內(nèi)存泄露:表示該被標(biāo)記為垃圾的數(shù)據(jù)沒(méi)有被標(biāo)記,內(nèi)存就會(huì)被永久的占用。除非把整個(gè)瀏覽器關(guān)閉,否則瀏覽器就會(huì)吃很多的內(nèi)存,無(wú)法再分配新的內(nèi)存用于存儲(chǔ)數(shù)據(jù)。*
深復(fù)制是什么鬼
var b = a
b = 2 //這個(gè)時(shí)候改變 b
a 完全不受 b 的影響
那么我們就說(shuō)這是一個(gè)深復(fù)制
對(duì)于簡(jiǎn)單類型的數(shù)據(jù)來(lái)說(shuō),賦值就是深拷貝。
對(duì)于復(fù)雜類型的數(shù)據(jù)(對(duì)象)來(lái)說(shuō),才要區(qū)分淺拷貝和深拷貝。
這是一個(gè)淺拷貝的例子
var a = {name: 'frank'}
var b = a
b.name = 'b'
a.name === 'b' // true
因?yàn)槲覀儗?duì) b 操作后,a 也變了
什么是深拷貝了,就是對(duì) Heap 內(nèi)存進(jìn)行完全的拷貝。
var a = {name: 'frank'}
var b = deepClone(a) // deepClone 還不知道怎么實(shí)現(xiàn)
b.name = 'b'
a.name === 'a' // true
對(duì)于基本類型變量,簡(jiǎn)單的賦值就是深拷貝。改變一個(gè)變量,不影響賦值的變量,兩者互不干擾。對(duì)于深淺拷貝,一般只討論復(fù)雜數(shù)據(jù)類型。
復(fù)雜類型變量,a等于b,a改變導(dǎo)致b也會(huì)改變,這就是淺拷貝。因?yàn)橹皇菍tack里面的地址復(fù)制了一份而已。復(fù)雜數(shù)據(jù)類型的深拷貝,會(huì)拷貝堆內(nèi)存里面的數(shù)據(jù),包括數(shù)據(jù)內(nèi)的引用,將不再引用同一個(gè)地址,而是引用新拷貝的數(shù)據(jù)的地址。