JS類型

NO IMAGE

數據類型

目前為至,js中共有8種數據類型(data type),分別是

  • 基本數據類型(primitive data type)
    • Undefined
    • Null(引用類型)
    • Boolean
    • Number
    • BigInt
    • String
    • Symbol
  • 複雜數據類型
    • Object
      • Function(值類型)
      • Array
      • Date
      • RegExp
      • ……

typeof操作符

因為js是一種弱類型語言,我們需要一種手段來檢測給定變量中值或者值的數據類型

js中的變量是沒有類型的,只有值才有。變量可以隨時持有任何類型的值

typeof就是負責提供這方面信息的操作符,然後返回一個字符串

很多人會錯以為typeof是一個函數

typeof是一個操作符 就像 let 一樣

所以我們在使用的時候是 typeof 變量

console.log(typeof undefined); //undefined
console.log(typeof null); //object
console.log(typeof true); // boolean
console.log(typeof 123); //number
console.log(typeof '123'); // string
console.log(typeof Symbol('test')); //symbol
let author = {
name: 'wcdaren',
sayName: () => {
console.log(this.name);
}
}
console.log(typeof author); //object

具體的為什麼答案是那個值,我們會在下面講解類型時說明

八種數據類型

Undefined

Undefined類型表示未定義(即聲明,但沒有初始化),只有一個值,即特殊的undefined.

undefined會被賦給一個沒有初始化的變量

let a 
console.log(a); //undefined
console.log(typeof a); //undefined

正常情況下,是不會顯式給一個值賦 undefined 的。undefined這個值的主要目的是用於比較,區別空對象指針(後面將要講到的null)和未初始化的變量。

not defined ≠ undefined

let a
console.log(a); //undefined
console.log(b); // ReferenceError: b is not defined

b is not defined 很容易讓人理解成 b is undefined。但是我們說過了 undefined:是已聲明瞭沒賦值

而這裡的b是沒有聲明,所以我們應該把 b is not defined 的意思是 變量b沒有聲明,即 b is not defined 應該換成 b is undeclared 。

typeof undeclared

但是,如果我們執行下面這段代碼

console.log(typeof a); //undefined

返回的竟然是undefined,是不是上面講的不對呢?不是的,沒有報錯而且返回一個undefined是因為typeof有一個特殊的安全防範機制(不會發生引用錯誤)。

對於未聲明過的變量,只能執行一項操作,即使用typeof操作符檢測其數據類型

當然,返回undeclared是比較更合理的。可惜不是這樣。

undefined不是關鍵字

值得一提的是,undefined在js中竟然不是關鍵字,即我們可以使用undefined作為變量名。那麼如果我們顯式地賦值,且不小心創建了一個undefined變量時,就會出現下面這種情況

let undefined = '123'
let a = undefined
console.log(a); //123

所以為了避免不小心篡改了undefined的值,我們可以使用 void 0來顯示的賦值

let undefined = '123'
let a = void 0
console.log(a); //undefined

但是還是如前面所說的,我們在編程中是不會顯式賦值undefined的

Null

Null類型表示定義了但是為空,只有一個值,即null

與undefined不顯式賦值剛好相反,如果我們需要一個變量,但是我們的值還沒獲得。

我們就會給這個變量定義null值

let a = null
console.log(a); //null
console.log(typeof null); //object

null需要注意的可能就是typeof null 返回的值

按正常的思考 我們覺得 應該返回的是 null

確實,返回null的想法是對的,這也是js公認的設計錯誤了

那為什麼返回的是一個object呢?

因為null是一個空的對象指針,所以null也算是一個對象即object

基於這上面這種情況,判斷一個值是否為空類型的最佳方法是直接和null比較

let a = null
console.log(a === null); //true

這裡又要注意一點 我們在js中基本使用 === 來比較 而不使用 == 來比較,因為 == 會默認自帶類型轉換 ,會帶來很多意想不到的結果

Boolean

Boolean類型有兩個值,true和false,表示邏輯上的真假

let a = true
let b = false
console.log(a); //true
console.log(b); //false
console.log(typeof a); //boolean
console.log(typeof b); //boolean

Number

let a = 123
let b = 1.2
console.log(a); //123
console.log(b); //1.2
console.log(typeof a);//number
console.log(typeof b);//number

根據語言規範,JavaScript 採用“遵循 IEEE 754 標準的雙精度 64 位格式”(”double-precision 64-bit format IEEE 754 values”)表示數字。

即,在js中不區分整數值和浮點值,所有數字均用浮點數值表示。

console.log(0.1 + 0.2);//0.30000000000000004

但是,在具體實現時,比如在瀏覽器中,整數值是以int類型存儲(32位),但當它被用於執行某些32位整型不支持的操作時就會自動轉換為上述的雙精度64位存儲。

console.log(1+2); //3

浮點數值

在上面中我們知道了

console.log(0.1 + 0.2);//0.30000000000000004

所以在涉及小數運算時

let a = 0.1
let b = 0.2
console.log((a + b) === 0.3); //false

永遠不要去測試某個特定的浮點數值

那如果我們要進行浮點數的數值判斷應該怎麼辦呢?這會在我們後續再講到。

進制

整數可以用十進制(基數為10)、十六進制(基數為16)、八進制(基數為8)以及二進制(基數為2)表示。

  • 十進制整數字面量由一串數字序列組成,且沒有前綴0。
  • 八進制的整數以 0(或0O、0o)開頭,只能包括數字0-7。
  • 十六進制整數以0x(或0X)開頭,可以包含數字(0-9)和字母 a~f 或 A~F。
  • 二進制整數以0b(或0B)開頭,只能包含數字0和1。

嚴格模式下,八進制整數字面量必須以0o或0O開頭,而不能以0開頭。

// 十進制
let a = 10
console.log(a); //10
// 八進制
let b1 = 070
let b2 = 0O70
let b3 = 0o070
console.log(b1); //56
console.log(b2); //56
console.log(b3); //56
// 十六進制
let c1 = 0xA
let c2 = 0Xa
console.log(c1); //10
console.log(c2); //10
// 二進制
let d1 = 0b0011
let d2 = 0B0011
console.log(d1); //3
console.log(d2);//3

數值範圍

5e-324~1.7976931348623157e+308

我們講在後面再介紹我們是如何得知這個範圍的。

console.log(Number.MIN_VALUE); //5e-324
console.log(Number.MAX_VALUE); //1.7976931348623157e+308

那如果我們真的要描述一個超過這個範圍的值該怎麼辦呢?這就有後面我們要講到的bigint類型

Infinity和-Infinity

值得一提的就是在其他語言中,如java,除以零是會拋錯的,而在js中除0會得到一個無窮大的數

無窮大又分正無窮和負無窮:Infinity和-Infinity

let a = 1/0
let b = -1/0
console.log(a); //Infinity
console.log(b); //-Infinity

NaN

NaN,即非數值(Not a Number)是一個特殊的數值,這個數值用於表示一個本來要返回數值的操作數未返回數值的情況(這樣就不會拋出錯誤了)。例如, 0除以 0

console.log(0 / 0); //NaN
console.log('wcdaren' - 100); //NaN

NaN值有兩個特點

  • 任何涉及NaN的操作都返回NaN
  • NaN與任何值都不相等,包括NaN本身
console.log(NaN / 10); //NaN
console.log(NaN === NaN); //false

BigInt

let a = 9007199254740992n
console.log(typeof a);//bigint

bigint,就是我們在談Number時,超過Number範圍的值的解決方法。

在涉及到類型轉換或者運算方面,我們可以簡單地理解為bigint和int是等效的。

但是實際上,他們兩者是不等同的。

尤其有一點需要注意的是bigint類型是無法和number類型一起運算的

let a = 1n
let b = 1
console.log(a + b); //報錯

String

字符串可以由雙引號(“)或單引號(‘)和反引號(`)表示。

//單引號
let name = 'wcdaren'
//雙引號
let email = "[email protected]"
//單雙混合
let address = "China ,'Guangzhou'"
let job = '"PM"'
//反引號
let girlfriend = `gugu`
console.log(name); //wcdaren
console.log(email); // [email protected]
console.log(address); //China ,'Guangzhou'
console.log(job); //"PM"
console.log(girlfriend);//gugu
console.log(typeof name); //string
console.log(typeof email);//string
console.log(typeof address);//string
console.log(typeof job);//string
console.log(typeof girlfriend);//string

反引號`是ES6新添加的語法,我們到時會再單獨介紹。

UTF-16編碼

js 中的字符串是一串Unicode 字符序列。再具體而言,即在js中字符串是一串UTF-16代碼單元(code unit)的序列,每一個代碼單元(code unit)由一個 16 位二進制數表示。每一個Unicode字符由一個或兩個代碼單元(code unit)來表示。

每個代碼單元可以表示 [U+0000,U+FFFF]範圍中的碼點(code point)。

碼點(code point):一個編碼表中的某個字符對應代碼值。

我們可以使用’\u1234’語法,即使用 [U+0000,U+FFFF]範圍中的碼點,獲得字符

console.log('\u0061'); //a

在js中還有以下的碼點來表示一個字符,我們在下面特殊字符再介紹

我們在前面說到,在js中每個Unicode字符由一個或兩個代碼單元來表示。

因為一旦碼點超過了U+FFFF,比如,馬這個表情 ——> 🐎

console.log('\ud83d\udc0e'); //🐎

可是如果使用這種語法,我們就很難確定這到底是一個字符還是兩個字符

所以我們還可以使用另一種書寫方式來表示兩個代碼單元即表示超過U+FFFF範圍的碼點

console.log('\u{1f40e}');//🐎

當然,這個只是一個語法糖,實際上🐎還是由兩個代碼單元組成的。

特殊字符

在String類型中包含一些特殊的字符,用於表示非打印字符來,或者據有其他用途的字符。

字符含義
\0Null字節
\b退格符
\f換頁符
\n換行符
\r回車符
\tTab (製表符)
\v垂直製表符
\’單引號(‘),在用單引號表示的字符串中使用
\”雙引號 , 在用雙引號表示的字符串中使用
\\反斜槓字符(\)
\XXX由從0到377最多三位八進制數XXX表示的 Latin-1 字符。例如,\251是版權符號的八進制序列。
\xXX由從00和FF的兩位十六進制數字XX表示的Latin-1字符。例如,\ xA9是版權符號的十六進制序列。
\uXXXX由四位十六進制數字XXXX表示的Unicode字符。例如,\ u00A9是版權符號的Unicode序列。見Unicode escape sequences (Unicode 轉義字符).
\u*{XXXXX}*Unicode碼點 (code point) 轉義字符。例如,\u{2F804} 相當於Unicode轉義字符 \uD87E\uDC04的簡寫。

嚴格模式下,不能使用八進制轉義字符。

console.log('句子從這裡開始結束\0,\0表示null,那麼我們在輸出字符時是從第一個遍歷直到遍歷到null,遍歷即結束,所以如果我們在字符串某個位置填上null值,字符串輸出便結束'); //句子從這裡開始結束
console.log('I\' a good man!'); //I' a good man!
console.log("you are a \"HaoRen\""); //you are a "HaoRen"
console.log('This is \\'); //This is \
// 範圍:0~377 \XXX (不推薦使用,嚴格模式不可使用)
console.log('\251'); //©
// 範圍:00~FF \xXX
console.log('\xA9'); //©
// 範圍:0000~FFFF
console.log('\u00a9'); //©
// 範圍:00000~FFFFF
console.log('\u{1f40e}');//🐎

字符串的特點

字符串是不可變的。所以在涉及修改字符串的時候,其實我們只不過是把銷燬原來的字符串後創建了新的字符串

let name = 'java'
name = name + 'script'
console.log(name); //javascript

上面的代碼在真實的操作是

  1. 創建一個能容納10個字符(即javascript的長度)的字符串
  2. 在這個字符串中填入’java’和’script’
  3. 銷燬原來的字符串’java’和字符串’script’

Symbol

let a = Symbol('123')
console.log(a); //Symbol(123)
console.log(typeof a); //symbol

它表示一個獨一無二的值(非字符串)。關於symbol,我們會在單獨在後面再講,這裡我們只要知道它是一個獨一無二的值就可以了。

Obejct

對象的創建,我們這裡先提兩種,也是最常用的兩種

  • 對象字面量
let a = {
name: 'wcdaren',
}
console.log(a); //{ name: 'wcdaren' }
console.log(typeof a); //object
  • 構造函數
let a = new Object(
{ name: 'wcdaren' }
)
console.log(a); //{ name: 'wcdaren' }
console.log(typeof a); //object

至此,js中類型的分類已經全部分完了。那函數和數組之類的呢?他們都隸屬於object,我們將在深入理解對象中介紹。

類型轉換

相關文章

排序演化(三):快速

排序演化(二):歸併

排序演化(一):希爾

Promises/A+實現,一條規範對應一段代碼