今天我們來(lái)理理JS的家族譜,也就是數(shù)據(jù)類型涡上。
本文大部分借鑒阮一峰先生的JS教程內(nèi)容债朵,用于作者學(xué)習(xí)。文末有原文鏈接鸣哀,給想具體了解更多的朋友學(xué)習(xí)。
成員的分類
JavaScript這個(gè)家族里面一共有七個(gè)成員吞彤,其中大致分為三類:基本類型我衬、特殊類型和復(fù)合類型。
基本類型
基本類型和特殊類型都是最原始的饰恕,不能再被分類挠羔,可以理解為在這個(gè)家族中這些成員是沒有單獨(dú)出去成家立業(yè)的,所以都是單身狗埋嵌。
number
數(shù)字類型破加,這第一條單身狗就是數(shù)字了
- 表示方式
就是直接表示和科學(xué)計(jì)數(shù)法兩種方式,不過有時(shí)候JS會(huì)將我們的數(shù)值自動(dòng)轉(zhuǎn)換成科學(xué)計(jì)數(shù)法雹嗦,就是在你的小數(shù)點(diǎn)前面的位數(shù)多于21位的時(shí)候范舀,還有就是首位是0,后面跟著5個(gè)以上的0時(shí)候了罪。表示小數(shù)的話如果整數(shù)位是0锭环,可以不寫0。
1234567890123456789012
// 1.2345678901234568e+21
0.0000001 // 1e-7
.1===0.1 // true
- 數(shù)值的進(jìn)制
直接表示的時(shí)候也是可以輸入十進(jìn)制之外的進(jìn)制數(shù)的泊藕,比如二進(jìn)制辅辩、八進(jìn)制、十六進(jìn)制娃圆。怎么區(qū)分這家伙的進(jìn)制數(shù)呢玫锋?
- 十進(jìn)制不戴帽子(首位什么也不加)
- 二進(jìn)制帶個(gè)帽子上面寫著0B/0b
- 八進(jìn)制戴的帽子上面寫著0
- 十六進(jìn)制的帽子上面寫著0X/0x
255 //255
0xff // 255
0377 // 255
0b11 // 3
數(shù)值的儲(chǔ)存方式
這個(gè)部分就很復(fù)雜了,簡(jiǎn)單地了解一下讼呢,數(shù)值的儲(chǔ)存方式是64位浮點(diǎn)數(shù)來(lái)儲(chǔ)存的撩鹿。我們需要特別注意的是,當(dāng)我們?cè)贘S中計(jì)算小數(shù)時(shí)悦屏,最后的結(jié)果很有可能并不精確三痰,在JS中直接計(jì)算小數(shù)時(shí)要特別小心吧寺。特殊的值
- NaN
當(dāng)判斷一個(gè)未知的數(shù)據(jù)類型是不是數(shù)字時(shí),假如不是散劫,就會(huì)返回一個(gè)特殊的值叫做NaN稚机,意思是非數(shù)字。這也是JS中唯一一個(gè)誰(shuí)都不等于的數(shù)據(jù)获搏,真正的獨(dú)苗一個(gè)赖条,因?yàn)樗约阂膊坏扔谧约骸?/li>
NaN !== NaN // true
- Infinity
這家伙有正負(fù)之分,叫做無(wú)窮常熙,數(shù)學(xué)符號(hào)是∞
- 幾個(gè)和數(shù)字相關(guān)的語(yǔ)句
- parseInt()// 英語(yǔ)的意思是解析整數(shù)纬乍,能把括號(hào)里面的東西轉(zhuǎn)化為字符串,然后讀取數(shù)字裸卫,遇到不是數(shù)字的就停止仿贬,返回已經(jīng)讀取好的數(shù)據(jù)。(一定是整數(shù)墓贿,因?yàn)樾?shù)點(diǎn)不能轉(zhuǎn)化)
- parseFloat()//英語(yǔ)的意思是解析浮點(diǎn)數(shù)茧泪,能把括號(hào)里面的東西轉(zhuǎn)化為浮點(diǎn)數(shù),就是能把小數(shù)點(diǎn)也識(shí)別出來(lái)聋袋。解析的時(shí)候發(fā)現(xiàn)解析不了的時(shí)候就停下來(lái)队伟,返回解析好的數(shù)據(jù)。
- isNaN()//這就是判斷括號(hào)里面的是不是NaN
- isFinity()//這命令是看數(shù)據(jù)是不是正常數(shù)據(jù)幽勒,只對(duì)+InFinity嗜侮、-InFinity、NaN啥容、undefined锈颗、返回false。
parseInt('123') // 123
parseFloat('3.14') // 3.14
isNaN(NaN) // true
isNaN(123) // false
isFinite(undefined) // false
isFinite(null) // true
string
字符串咪惠,我們介紹的第二名成員宜猜,是個(gè)大明星,平常出門挺拉風(fēng)硝逢,經(jīng)常帶著單引號(hào)和雙引號(hào)兩個(gè)小弟出門。不過有時(shí)候绅喉,也想低調(diào)點(diǎn)渠鸽,不帶引號(hào)也能出現(xiàn)。
- 轉(zhuǎn)義--我們已經(jīng)知道了柴罐,表示字符串出場(chǎng)的符號(hào)就是單雙引號(hào)徽缚,那么當(dāng)我們想在字符串里面再使用單雙引號(hào)時(shí),會(huì)造成一定的錯(cuò)誤革屠,系統(tǒng)并不知道你是想表示引號(hào)結(jié)束還是想加入一個(gè)引號(hào)的字符串凿试。所以必須使用轉(zhuǎn)義來(lái)實(shí)現(xiàn)排宰。常見的幾個(gè)轉(zhuǎn)義:
- /0 表示null
- /' 表示單引號(hào)
- /" 表示雙引號(hào)
- /n 表示換行
- /r 表示回車
- // 表示/
console.log('1\n2')
// 1
// 2
- / 的作用還有另外這一種, 那就是在后面直接接Unicode碼那婉,可以是3個(gè)八進(jìn)制板甘,也可以是兩個(gè)十六進(jìn)制,或者4個(gè)十六進(jìn)制详炬。
'\u007A' === 'z' // true
- 多行字符串-- 在每一行末尾加上\就可以換行輸出字符盐类,但是這樣假如\后面有空格,就會(huì)報(bào)錯(cuò)呛谜,所以更合適的寫法是'字符'+'字符'的寫法在跳。
var longString = 'Long '
+ 'long '
+ 'long '
+ 'string';
有一些字符識(shí)別長(zhǎng)度的問題,因?yàn)镴S發(fā)明的時(shí)候UTF-8還沒有發(fā)明出來(lái)隐岛,所以JS只支持部分支持UTF-16猫妙,當(dāng)我們Unicode碼點(diǎn)在U+10000~U+10FFFF時(shí),會(huì)錯(cuò)誤識(shí)別字符長(zhǎng)度為2聚凹。
Base64轉(zhuǎn)碼--兩個(gè)語(yǔ)句
- btoa():任意值轉(zhuǎn)化成Base64
- atob() : Base64轉(zhuǎn)化成原值
當(dāng)非ASCⅡ要轉(zhuǎn)入時(shí)割坠,要加一層轉(zhuǎn)碼如下:
function b64Encode(str) {
return btoa(encodeURIComponent(str));
}
function b64Decode(str) {
return decodeURIComponent(atob(str));
}
b64Encode('你好') // "JUU0JUJEJUEwJUU1JUE1JUJE"
b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE') // "你好"
boolean
boolean值是我們介紹的第三個(gè)基本類型,它的值只有兩個(gè)元践,那就是true和false韭脊,表示真假。當(dāng)我們使用判斷表達(dá)式時(shí)单旁,就會(huì)返回我們一個(gè)布爾值沪羔,這里介紹6種值直接轉(zhuǎn)化成false
- undefined
- null
- false
- 0
- NaN
- 空字符串
if ('') {
console.log('true');
}
// 因?yàn)榭兆址疄閒alse所以,console.log不執(zhí)行
symbol
是ES6中新來(lái)的成員象浑,這里暫時(shí)不做介紹蔫饰。
特殊類型
undefined & null
這是兩個(gè)雙胞胎兄弟,只是名字不同愉豺,其他的幾乎一模一樣篓吁,都表示什么都沒有,具體含義undefined表示沒有定義蚪拦,null表示空杖剪,那么區(qū)別是:
- 當(dāng)一個(gè)變量沒有賦值,那么返回undefined
- 如果想有一個(gè)對(duì)象驰贷,但還沒有賦值盛嘿,推薦使用null
- 如果有一個(gè)非對(duì)象,且不想給他賦值括袒,使用undefined(直接不賦值即可)
復(fù)合類型
復(fù)合類型就一個(gè)object(對(duì)象)次兆,不過這和之前介紹的所有數(shù)據(jù)類型都不一樣,他自己成家立業(yè)锹锰,家里還有數(shù)組(array)芥炭、函數(shù)(function)和其他的對(duì)象漓库。
定義
對(duì)象的定義方法是{}(在數(shù)組中用[]定義,函數(shù)是function開頭)格式 {} 里面是key:value的格式园蝠,key一般叫做對(duì)象的屬性渺蒿,或者鍵名,而value一般叫做鍵值砰琢,屬性值蘸嘶。
key
在對(duì)象里面所有的key都是字符串格式,如果key名稱符合標(biāo)識(shí)符的規(guī)則陪汽,或者是純數(shù)字训唱,則系統(tǒng)自動(dòng)添加單引號(hào),可以在對(duì)象里面不寫單引號(hào)挚冤。不過在定義之外的區(qū)域况增,除非系統(tǒng)能自動(dòng)轉(zhuǎn)化,不然還是要加上單引號(hào)训挡。value
value的值可以是任意的數(shù)據(jù)類型甚至可以又是一個(gè)對(duì)象澳骤,所以object的內(nèi)部是非常多樣。查看
所有的讀取和更改都是在我們知道這個(gè)對(duì)象有哪些屬性的情況下澜薄,那么怎么知道這個(gè)對(duì)象有哪些屬性呢为肮?有一種命令:Object.keys(對(duì)象)
var obj = {
key1: 1,
key2: 2
};
Object.keys(obj);
// ['key1', 'key2']
- 讀取
當(dāng)我們定義好對(duì)象之后,我們?nèi)绾握{(diào)用這個(gè)對(duì)象呢肤京?通常情況下我們并不會(huì)把對(duì)象原模原樣地照抄到其他地方颊艳,而是使用一個(gè)變量來(lái)保存我們的對(duì)象(想想一個(gè)比較多的數(shù)組或者函數(shù)你粘貼也累呀)。使用賦值語(yǔ)句 變量 = object
var obj = {
p: 'Hello World'
}
obj.p // "Hello World"
obj['p'] // "Hello World"
可是我們有時(shí)候并不想把對(duì)象全部拿出來(lái)調(diào)用忘分,就想拿出其中的一個(gè)屬性名和屬性值修改下棋枕。這個(gè)時(shí)候就使用格式:object['屬性名'] 意思是調(diào)用對(duì)象的某個(gè)屬性,假如你的屬性名符合標(biāo)識(shí)符的命名規(guī)則妒峦,那么也可以寫成object.屬性名重斑。
- 更改/添加
對(duì)象的屬性名和屬性值是可以定義后,再進(jìn)行修改或者添加的肯骇。我們按照上述方式讀取之後窥浪,通過賦值語(yǔ)句添加屬性并修改
var obj = {};
obj.foo = 'Hello';
obj['bar'] = 'World';
在這個(gè)例子中,原本的對(duì)象里面并沒有自身的屬性存在笛丙,在后面我們調(diào)用了對(duì)象漾脂,直接用讀取的方式來(lái)聲明屬性名,并且賦值給屬性若债,這樣就添加了屬性其中。
- 刪除
既然有添加拆融,就一定有刪除蠢琳。方式是:調(diào)用這對(duì)象的具體屬性啊终,然后在前面添加delete命令
delete obj.p
不過有些屬性是不能刪除的,執(zhí)行這個(gè)命令會(huì)報(bào)錯(cuò)傲须。
- 判斷屬性是否在對(duì)象里面
其實(shí)我們通過讀取的方式也可以判斷屬性在不在對(duì)象里面蓝牲,不過這里還有一種方式直接告訴你在還是不在,那就是: 屬性名 in 對(duì)象 --返回布爾值
var obj = { p: 1 };
'p' in obj // true
要注意的是繼承屬性也會(huì)看到泰讽,如果要判斷是不是繼承屬性可以用
obj.hasOwnProperty('屬性名')
- for···in遍歷
可以將對(duì)象每一個(gè)屬性遍歷一次
for (var i in obj) {
console.log('屬性名:', i)
}
不可遍歷的屬性例衍,則不讀。繼承屬性如果可遍歷是是可讀的已卸。
- with 批量操作
其實(shí)with就是想把一個(gè)對(duì)象里面的屬性在一個(gè)代碼塊操作
var obj = {
p1: 1,
p2: 2
}
with (obj) {
p1 = 4;
p2 = 5;
}
// 等同于
obj.p1 = 4;
obj.p2 = 5;
但是有個(gè)問題在于假如里面沒有你要操作的屬性佛玄,你卻寫進(jìn)了with的語(yǔ)句,那就是聲明當(dāng)前作用域的變量了累澡,聲明也就算了梦抢,好歹你把這個(gè)當(dāng)成屬性和屬性值加進(jìn)去呀,但因?yàn)槭亲兞坷⒂矗蛯傩灾蛋朊X關(guān)系都沒有奥吩,所以屬性也沒能加進(jìn)去。也就是說蕊梧,假如object里面并沒有with中你要操作的屬性霞赫,那么你就等著出bug吧!
說說對(duì)象里的函數(shù)(這里不談函數(shù)具體的用法)
- 沒有函數(shù)這種數(shù)據(jù)結(jié)構(gòu)
函數(shù)可以說是對(duì)象里面最NB的存在肥矢,為什么是對(duì)象(object)里面呢端衰?因?yàn)樗?strong>對(duì)象這種數(shù)據(jù)類型的一種,他本身并不是一種數(shù)據(jù)類型i夏āQテ取!最厲害的還是我們所說的七種數(shù)據(jù)類型楼誓。那么為啥NB玉锌?因?yàn)橐簿褪菦]有這個(gè)名分,實(shí)力和顏值都讓他成為JS里面的一等公民疟羹,簡(jiǎn)直屌絲逆襲的典范主守。
function f() {}
typeof f
// "function"
typeof是一種查看數(shù)據(jù)類型的命令,所以從上面你看到了什么榄融,對(duì)参淫,function,但是注意愧杯,沒有function這種數(shù)據(jù)結(jié)構(gòu)O巡拧!!這是一個(gè)bug耍铜,但是也可以理解為function在JS中的地位幾乎和其他數(shù)據(jù)結(jié)構(gòu)一模一樣邑闺。
- 函數(shù)名也能提升
這是又一個(gè)厲害之處,在JS中棕兼,用函數(shù)命令聲明函數(shù)時(shí)
function f() {}
和變量名一樣,會(huì)被提升到JS的頂部
- 函數(shù)內(nèi)部變量提升
和全局變量提升一個(gè)道理陡舅,只不過變成了函數(shù)內(nèi)部的局部變量提升,提到函數(shù)的開頭伴挚,感覺都有自己的小宇宙(作用域)了靶衍。
一句話說說對(duì)象里的數(shù)組(array)
不太準(zhǔn)確地描述:屬性名是自然數(shù)有序序列的字符串的特殊對(duì)象。