JavaScript數(shù)據(jù)類型
萬丈高樓平地起,萬變不離其宗,扎實(shí)的基本功對于一個研發(fā)人員來說相當(dāng)重要,此文從常見面試題著手,以文字思維導(dǎo)圖的形式回顧總結(jié)JavaScript的數(shù)據(jù)類型,偶爾閱讀此文,能夠查漏補(bǔ)缺、加深印象。
面試題引入
js有哪幾種數(shù)據(jù)類型?其中基本數(shù)據(jù)類型是哪些?
5s回想
回答前的旁白:
從結(jié)構(gòu)上看,所有的數(shù)據(jù)(data)最終都可以分解成三種類型:
標(biāo)量(scalar),也就是一個單獨(dú)的字符串(string)或數(shù)字(number),比如"北京"這個單獨(dú)的詞。
序列(sequence),也就是若干個相關(guān)的數(shù)據(jù)按照一定順序并列在一起,又叫做數(shù)組(array)或列表(List),比如"北京,上海"。
映射(mapping),也就是一個名/值對(Name/value),即數(shù)據(jù)有一個名稱,還有一個與之相對應(yīng)的值,這又稱作散列(hash)或字典(dictionary),比如"首都:北京"。
json:
Douglas Crockford聲稱的永遠(yuǎn)不必升級的規(guī)則:
1) 并列的數(shù)據(jù)之間用逗號(",")分隔
2) 映射用冒號(":")表示
3) 并列數(shù)據(jù)的集合(數(shù)組)用方括號("[]")表示
4) 映射的集合(對象)用大括號("{}")表示
例子:"北京市的面積為16800平方公里,常住人口1600萬人。上海市的面積為6400平方公里,常住人口1800萬。"
=> [
{"城市":"北京","面積":16800,"人口":1600},
{"城市":"上海","面積":6400,"人口":1800}
]
分類:
基本數(shù)據(jù)類型(值類型、原始類型):
包括:
undefined
定義:表示“無”的原始值、未定義,轉(zhuǎn)為數(shù)值時為NaN
場景:
變量聲明,但沒有賦值
調(diào)用函數(shù)時,應(yīng)該提供的參數(shù)沒有提供,該參數(shù)等于undefined
對象沒有賦值的屬性
函數(shù)沒有返回值時,默認(rèn)返回undefined
null
定義:表示“無”的對象、空值,轉(zhuǎn)為數(shù)值時為0
場景:調(diào)用函數(shù)時,不需要傳入某個參數(shù),這時就可以傳入null
注意:typeof(null)返回'object'
boolean
定義:表示“真”(true)和“假”(false)兩個狀態(tài)
場景:
兩元邏輯運(yùn)算符: && ,||
前置邏輯運(yùn)算符: !
相等運(yùn)算符:===,!==,==,!=
比較運(yùn)算符:>,>=,<,<=
自動轉(zhuǎn)換:
false:undefined, null, false, 0, NaN, ""或''
true:除了轉(zhuǎn)為false的外都轉(zhuǎn)為true,特別的[], {}
應(yīng)用:用于程序流程的控制
number
概述
整數(shù)和浮點(diǎn)數(shù)
所有數(shù)字都是以64位浮點(diǎn)數(shù)形式儲存,1與1.0是相同的,是同一個數(shù)1 === 1.0 => true
注意:
某些運(yùn)算只有整數(shù)才能完成,此時JavaScript會自動把64位浮點(diǎn)數(shù),轉(zhuǎn)成32位整數(shù)
浮點(diǎn)數(shù)不是精確的值 0.1 + 0.2 === 0.3, (0.3 - 0.2) === (0.2 - 0.1) => false
數(shù)值精度
國際標(biāo)準(zhǔn)IEEE 754:
第1位:符號位,0表示正數(shù),1表示負(fù)數(shù)
第2位到第12位:儲存指數(shù)部分(11個二進(jìn)制)
第13位到第64位:儲存小數(shù)部分(即有效數(shù)字)
精度:-(2e53-1)到2e53-1,超過無法保持精度
數(shù)值范圍
指數(shù)范圍:最大2e11-1 => 2047
數(shù)值范圍:2e1024到2e-1023,超過不能表示
正向溢出:指數(shù)部分等于或超過最大正值1024 => Infinity
負(fù)向溢出:指數(shù)部分等于或超過最小負(fù)值-1023 => 0
最大值:Number.MAX_VALUE => 1.7976931348623157e+308
最小值:Number.MIN_VALUE => 5e-324
表示法
字面量
35(十進(jìn)制)和0xFF(十六進(jìn)制)
科學(xué)計(jì)數(shù)法
123e3 => 123000,123e-3 => 0.123
自動轉(zhuǎn)科學(xué)計(jì)數(shù)法
小數(shù)點(diǎn)前的數(shù)字多于21位
小數(shù)點(diǎn)后的零多于5個
進(jìn)制
十進(jìn)制:沒有前導(dǎo)0的數(shù)值
八進(jìn)制:有前綴0o或0O的數(shù)值,或者有前導(dǎo)0、且只用到0-7的七個阿拉伯?dāng)?shù)字的數(shù)值
十六進(jìn)制:有前綴0x或0X的數(shù)值
二進(jìn)制:有前綴0b或0B的數(shù)值
特殊數(shù)值
正零和負(fù)零
區(qū)別:+0或-0當(dāng)作分母,返回的值是不相等
1 / +0 => +Infinity
1 / -0 => -Infinity
NaN
定義:“非數(shù)字”(Not a Number)
場景:
將字符串解析成數(shù)字出錯 5 - 'x' => NaN
數(shù)學(xué)函數(shù)的運(yùn)算結(jié)果
Math.acos(2) => NaN
Math.log(-1) => NaN
Math.sqrt(-1) => NaN
0 / 0 => NaN
運(yùn)算規(guī)則:
NaN === NaN => false
[NaN].indexOf(NaN) => -1
Boolean(NaN) => false
NaN + 32 => NaN
判斷方法:
isNaN(NaN) => true
注意:只對數(shù)值有效,其他值要先轉(zhuǎn)換成數(shù)值
注意:
NaN不是一種獨(dú)立的數(shù)據(jù)類型
是一種特殊數(shù)值,typeof NaN => 'number'
Infinity
定義:
正的數(shù)值太大,或一個負(fù)的數(shù)值太小,無法表示
非0數(shù)值除以0,得到Infinity
有正負(fù)之分
運(yùn)算規(guī)則:略
isFinite:返回一個布爾值,檢查某個值是不是正常數(shù)值,而不是Infinity
isFinite(Infinity) => false,isFinite(NaN) => false,isFinite(-1) => true
全局方法
parseInt()
將字符串轉(zhuǎn)為整數(shù)
進(jìn)制轉(zhuǎn)換
parseFloat()
將一個字符串轉(zhuǎn)為浮點(diǎn)數(shù)
Number對象實(shí)例方法
toString 把數(shù)字轉(zhuǎn)換為字符串,使用指定的基數(shù)。
toLocaleString 把數(shù)字轉(zhuǎn)換為字符串,使用本地?cái)?shù)字格式順序。
toFixed 把數(shù)字轉(zhuǎn)換為字符串,結(jié)果的小數(shù)點(diǎn)后有指定位數(shù)的數(shù)字。
toExponential 把對象的值轉(zhuǎn)換為指數(shù)計(jì)數(shù)法。
toPrecision 把數(shù)字格式化為指定的長度。
valueOf 返回一個 Number 對象的基本數(shù)字值。
string
概述
定義
轉(zhuǎn)義:反斜杠(\)轉(zhuǎn)義符,表示特殊字符
特殊:
三個八進(jìn)制數(shù):'\251' => "?"
兩個十六進(jìn)制數(shù):'\xA9' => "?"
四個十六進(jìn)制數(shù):'\u00A9' => "?"
字符串與數(shù)組
相同取值方式,不可賦值
使用數(shù)據(jù)方法:Array.prototype.join.call(s, ' ')
長度
length不可改
字符集
Unicode
Base64轉(zhuǎn)碼
處理特殊字符,方便打印
btoa():字符串或二進(jìn)制值轉(zhuǎn)為Base64編碼
atob():Base64編碼轉(zhuǎn)為原來的編碼
非ASCII碼字符(漢字)轉(zhuǎn)為Base64編碼:
btoa(encodeURIComponent(str))
String對象方法:
anchor() 創(chuàng)建 HTML 錨。
big() 用大號字體顯示字符串。
blink() 顯示閃動字符串。
bold() 使用粗體顯示字符串。
charAt() 返回在指定位置的字符。
charCodeAt() 返回在指定的位置的字符的 Unicode 編碼。
concat() 連接字符串。
fixed() 以打字機(jī)文本顯示字符串。
fontcolor() 使用指定的顏色來顯示字符串。
fontsize() 使用指定的尺寸來顯示字符串。
fromCharCode() 從字符編碼創(chuàng)建一個字符串。
indexOf() 檢索字符串。
italics() 使用斜體顯示字符串。
lastIndexOf() 從后向前搜索字符串。
link() 將字符串顯示為鏈接。
localeCompare() 用本地特定的順序來比較兩個字符串。
match() 找到一個或多個正則表達(dá)式的匹配。
replace() 替換與正則表達(dá)式匹配的子串。
search() 檢索與正則表達(dá)式相匹配的值。
slice() 提取字符串的片斷,并在新的字符串中返回被提取的部分。
small() 使用小字號來顯示字符串。
split() 把字符串分割為字符串?dāng)?shù)組。
strike() 使用刪除線來顯示字符串。
sub() 把字符串顯示為下標(biāo)。
substr() 從起始索引號提取字符串中指定數(shù)目的字符。
substring() 提取字符串中兩個指定的索引號之間的字符。
sup() 把字符串顯示為上標(biāo)。
toLocaleLowerCase() 把字符串轉(zhuǎn)換為小寫。
toLocaleUpperCase() 把字符串轉(zhuǎn)換為大寫。
toLowerCase() 把字符串轉(zhuǎn)換為小寫。
toUpperCase() 把字符串轉(zhuǎn)換為大寫。
toSource() 代表對象的源代碼。
toString() 返回字符串。
valueOf() 返回某個字符串對象的原始值。
特點(diǎn):
1) 占用空間固定,保存在棧中
2) 保存與復(fù)制的是值本身
3) 使用typeof檢測數(shù)據(jù)類型
合成數(shù)據(jù)類型(引用類型):
包括:
object:
理解:
(1)“對象”是單個實(shí)物的抽象。
一本書、一輛汽車、一個人,一個數(shù)據(jù)庫、一張網(wǎng)頁、一個與遠(yuǎn)程服務(wù)器的連接也可以是“對象”。當(dāng)實(shí)物被抽象成“對象”,實(shí)物之間的關(guān)系就變成了“對象”之間的關(guān)系,從而就可以模擬現(xiàn)實(shí)情況,針對“對象”進(jìn)行編程。
(2)“對象”是一個容器,封裝了“屬性”(property)和“方法”(method)。
所謂“屬性”,就是對象的狀態(tài);所謂“方法”,就是對象的行為(完成某種任務(wù))。比如,我們可以把動物抽象為animal對象,“屬性”記錄具體是那一種動物,“方法”表示動物的某種行為(奔跑、捕獵、休息等等)。
分類:
狹義的對象(object)
概述
生成方法
var o1 = {};
var o2 = new Object();
var o3 = Object.create(null);
鍵名
都是字符串
鍵名是數(shù)值,會被自動轉(zhuǎn)為字符串
不符合標(biāo)識名的條件,必須加引號
屬性
任何數(shù)據(jù)類型
對象的引用
指向同一個內(nèi)存地址,修改其中一個變量,會影響到其他所有變量。
屬性操作
讀?。? []
賦值:. []
所有:Object.keys(o);
刪除:delete可以刪除的
檢查:in
遍歷:for...in
所有可遍歷(enumerable)的屬性,跳過不可遍歷的屬性
對象自身的屬性 + 繼承的屬性
with語句
一般模板引擎的原理
Object靜態(tài)方法
(0)Object.keys(),Object.getOwnPropertyNames()
(1)對象屬性模型的相關(guān)方法
Object.getOwnPropertyDescriptor():獲取某個屬性的attributes對象。
Object.defineProperty():通過attributes對象,定義某個屬性。
Object.defineProperties():通過attributes對象,定義多個屬性。
Object.getOwnPropertyNames():返回直接定義在某個對象上面的全部屬性的名稱。
(2)控制對象狀態(tài)的方法
Object.preventExtensions():防止對象擴(kuò)展。
Object.isExtensible():判斷對象是否可擴(kuò)展。
Object.seal():禁止對象配置。
Object.isSealed():判斷一個對象是否可配置。
Object.freeze():凍結(jié)一個對象。
Object.isFrozen():判斷一個對象是否被凍結(jié)。
(3)原型鏈相關(guān)方法
Object.create():生成一個新對象,并該對象的原型。
Object.getPrototypeOf():獲取對象的Prototype對象。
Object實(shí)例方法
valueOf():返回當(dāng)前對象對應(yīng)的值。
toString():返回當(dāng)前對象對應(yīng)的字符串形式。
toLocaleString():返回當(dāng)前對象對應(yīng)的本地字符串形式。
hasOwnProperty():判斷某個屬性是否為當(dāng)前對象自身的屬性,還是繼承自原型對象的屬性。
isPrototypeOf():判斷當(dāng)前對象是否為另一個對象的原型。
propertyIsEnumerable():判斷某個屬性是否可枚舉。
數(shù)組(array)
定義:有序集合,特殊的對象
length
32位整數(shù),保存數(shù)組的元素個數(shù),最大值2e32 - 1
成員刪除:length比實(shí)際小
數(shù)組清空:length=0
類數(shù)組對象
arguments,需要call方法來使用數(shù)組方法
in
適用于數(shù)組
空位
某個位置是空元素
空位不影響length
最后一個逗號不產(chǎn)生空位
delete可產(chǎn)生
遍歷跳過
forEach方法、for...in結(jié)構(gòu)、以及Object.keys
靜態(tài)方法
Array.isArray(a)
實(shí)例方法
concat() 連接兩個或更多的數(shù)組,并返回結(jié)果。
join() 把數(shù)組的所有元素放入一個字符串。元素通過指定的分隔符進(jìn)行分隔。
pop() 刪除并返回?cái)?shù)組的最后一個元素
push() 向數(shù)組的末尾添加一個或更多元素,并返回新的長度。
reverse() 顛倒數(shù)組中元素的順序。
shift() 刪除并返回?cái)?shù)組的第一個元素
slice() 從某個已有的數(shù)組返回選定的元素
sort() 對數(shù)組的元素進(jìn)行排序
splice() 刪除元素,并向數(shù)組添加新元素。
toSource() 返回該對象的源代碼。
toString() 把數(shù)組轉(zhuǎn)換為字符串,并返回結(jié)果。
toLocaleString() 把數(shù)組轉(zhuǎn)換為本地?cái)?shù)組,并返回結(jié)果。
unshift() 向數(shù)組的開頭添加一個或更多元素,并返回新的長度。
valueOf() 返回?cái)?shù)組對象的原始值
函數(shù)(function)
特點(diǎn):
1) 占用空間不固定,保存在堆中
2) 保存與復(fù)制的是對象的一個指針(需要對象拷貝的原因)
3) 使用instanceof檢測數(shù)據(jù)類型
es6新類型:
symbol符號對象
定義:允許你創(chuàng)建唯一標(biāo)識符
使用:obj = Symbol(desc)
檢測:typeof(Symbol) => symbol
理解:
Symbol,表示獨(dú)一無二的值。對象的屬性名現(xiàn)在可以有兩種類型,一種是原來就有的字符串,另一種就是新增的Symbol類型。凡是屬性名屬于Symbol類型,就都是獨(dú)一無二的,可以保證不會與其他屬性名產(chǎn)生沖突。
Symbol 不可以使用new關(guān)鍵字,Symbol函數(shù)可以接受字符串參數(shù)使其返回值容易被區(qū)分,只是作為描述,即使參數(shù)相同Symbol函數(shù)返回值也不等。
Symbol值作為對象屬性名時,不能用點(diǎn)運(yùn)算符。同理,在對象的內(nèi)部,使用Symbol值定義屬性時,Symbol值必須放在方括號之中。
Symbol作為屬性名,該屬性不會出現(xiàn)在for…in、for…of循環(huán)中,也不會被Object.keys()、Object.getOwnPropertyNames()返回。但是,它也不是私有屬性,有一個Object.getOwnPropertySymbols方法,可以獲取指定對象的所有Symbol屬性名。
Symbol.for方法接受一個字符串作為參數(shù),然后搜索有沒有以該參數(shù)作為名稱的Symbol值。如果有,就返回這個Symbol值,否則就新建并返回一個以該字符串為名稱的Symbol值。注意,Symbol函數(shù)是總是返回新的值。
例子:
var a = Symbol('foo');
var b = Symbol('foo');
var s1 = Symbol.for('foo');
var s2 = Symbol.for('foo');
s1 === s2 => true
a === b => false
a === s2 => false
Symbol.keyFor(s1) => "foo"
Symbol.keyFor(a) => undefined
其他:
Symbol.hasInstance
此方法可確定構(gòu)造函數(shù)對象是否會將對象識別為構(gòu)造函數(shù)實(shí)例之一。 它由 instanceof 運(yùn)算符在內(nèi)部使用。
Symbol.isConcatSpreadable
此屬性返回一個布爾值,該值指示是否應(yīng)通過 Array.concat 將對象平展至其數(shù)組元素。
Symbol.iterator
此方法返回對象的默認(rèn)迭代器。 它由 for…of 語句在內(nèi)部使用。
Symbol.toPrimitive
此方法將對象轉(zhuǎn)換為相應(yīng)的基元值。 它由 ToPrimitive 抽象運(yùn)算符在內(nèi)部使用。
Symbol.toStringTag
此屬性返回一個字符串值,用于幫助創(chuàng)建對象的默認(rèn)字符串說明。 它由內(nèi)置方法 Object.toString 方法在內(nèi)部使用。
Symbol.unscopables
此屬性返回一個對象,該對象的屬性從關(guān)聯(lián)對象的 with 環(huán)境綁定中排除。
數(shù)據(jù)類型轉(zhuǎn)換:
強(qiáng)制轉(zhuǎn)換
Number()
原始類型:有不能轉(zhuǎn)為數(shù)字的,就是NaN
Number(false) => 0
Number(true) => 1
Number(undefined) => NaN
Number(null) => 0
Number("1.2") => 1.2
Number("12") => 12
Number("1.2.3") => NaN
Number(new object()) => NaN
Number(50) => 50
Number({}) => NaN
String()
原始類型值的轉(zhuǎn)換規(guī)則
數(shù)值:轉(zhuǎn)為相應(yīng)的字符串。
字符串:轉(zhuǎn)換后還是原來的值。
布爾值:true轉(zhuǎn)為"true",false轉(zhuǎn)為"false"。
undefined:轉(zhuǎn)為"undefined"。
null:轉(zhuǎn)為"null"。
String({a: 1}) => "[object Object]"
String([1, 2, 3]) => "1,2,3"
Boolean()
false
undefined
null
-0
0或+0
NaN
false
''
true
所有對象,包括{}、布爾對象new Boolean(false)
自動轉(zhuǎn)換
場景:
不同類型的數(shù)據(jù)互相運(yùn)算
123 + 'abc' => "123abc"
對非布爾值類型的數(shù)據(jù)求布爾值
if ('abc')
對非數(shù)值類型的數(shù)據(jù)使用一元運(yùn)算符(即“+”和“-”)
+ {foo: 'bar'} => NaN
本質(zhì):
以強(qiáng)制類型為基礎(chǔ),轉(zhuǎn)為需要的number、string、boolean
數(shù)據(jù)類型檢測:
typeof運(yùn)算符
數(shù)值、字符串、布爾值、undefined、函數(shù),返分別返回number、string、boolean、undefined、function
除此以外,其他情況都返回object
typeof window => "object"
typeof {} => "object"
typeof [] => "object"
typeof null => "object"
instanceof運(yùn)算符
定義:返回一個布爾值,表示指定對象是否為某個構(gòu)造函數(shù)的實(shí)例
實(shí)質(zhì):是檢查右邊構(gòu)建函數(shù)的原型對象,是否在左邊對象的原型鏈上
v instanceof Vehicle 等價于 Vehicle.prototype.isPrototypeOf(v)
instanceof對整個原型鏈上的對象都有效,因此同一個實(shí)例對象,可能會對多個構(gòu)造函數(shù)都返回true
特例:Object.create(null) instanceof Object => false,除了這個其他對象的數(shù)據(jù)類型都可以這么判斷
注意:instanceof運(yùn)算符只能用于對象,不適用原始類型的值
Object.prototype.toString(value)方法
相對準(zhǔn)確的檢測方法
Object.prototype.toString.call(value);
返回值
數(shù)值:返回[object Number]。
字符串:返回[object String]。
布爾值:返回[object Boolean]。
undefined:返回[object Undefined]。
null:返回[object Null]。
數(shù)組:返回[object Array]。
arguments對象:返回[object Arguments]。
函數(shù):返回[object Function]。
Error對象:返回[object Error]。
Date對象:返回[object Date]。
RegExp對象:返回[object RegExp]。
其他對象:返回[object " + 構(gòu)造函數(shù)的名稱 + "]