JavaScript面試 - 數據類型篇

衆所周知 JavaScript(一下簡稱 Js) 是一門弱類型語言,變量的類型不夠明確,不一樣類型之間能夠相互賦值。
Js 的數據類型能夠分爲兩大類:
\color{blue}{一、基礎數據類型}
\color{blue}{二、引用數據類型}es6

一、基礎數據類型

基礎數據類型包含如下 \color{red}{6} 中:數組

  • Number
  • String
  • Boolean
  • undefined
  • null
  • Symbol (es6 新增的一種基礎數據類型)

1-一、Number

1-1-一、聲明的幾種方式:

// 字面量的形式聲明
var num = 23
console.log(num) // 23

// 實例化的形式聲明
var num = new Number(23)
console.log(num) // 23

複製代碼

1-1-二、Number 類型包含了 int、浮點數、科學記數法、八進制數和十六進制數及特殊的 Number 值

1-1-2-一、int

var num = 23
複製代碼

1-1-2-二、浮點數

var num = 23.5
複製代碼

1-1-2-三、科學記數法 E/e

var num = 1.5e12 // 表示1.5乘以10的7次方
var num = 1.5-e12 // 表示1.5除以10的7次方
複製代碼

1-1-2-四、八進制

已 0 開頭,後面的數字爲任意的 0-7bash

var num = 070 // 等於十進制的 56
複製代碼

轉換規則:7 x 8^1 + 7 x 8^0 = 56函數

1-1-2-五、十六進制

已 0x 開頭,後面的數字爲任意的 0-F (字母能夠是大寫的,也能夠是小寫的)測試

var num = 0x1f // 等於十進制的 31
複製代碼

轉換規則:1 x 16^1 + 15 x 16^0 = 31ui

\color{red}{提示:}儘管全部整數均可以表示爲八進制或十六進制的字面量,但全部數學運算返回的都是十進制結果。編碼

1-1-2-六、特殊的 Number 值

  • Number.MAX_VALUE(Infinity) 和 Number.MIN_VALUE(-Infinity) 無窮大 和 無窮小 (能夠對任何數調用 isFinite() 方法,以確保該數不是無窮大)
  • NaN 表示非數(Not a Number)。通常說來,這種狀況發生在類型(String、Boolean 等)轉換失敗時。\color{red}{NaN 的另外一個奇特之處在於,它與自身不相等。}
console.log(NaN == NaN) // false
console.log(NaN === NaN) // false
複製代碼

\color{red}{因此在判斷是否是 NaN 的時候,推薦使用 isNaN()}

console.log(isNaN(NaN)) // true
console.log(isNaN(6)) // false
複製代碼

1-二、String

1-2-三、聲明方式

// 字面量的形式聲明
var str = 'hello'
console.log(str) // hello

// 實例化的形式聲明
var str = new String("hello")
console.log(str) // hello
複製代碼

由上能夠得出: \color{red}{在 Js 中咱們能夠經過雙引號,單引號來聲明字符串,可是自身不能包裹自身(雙引號不能包含雙引號)}

1-三、Boolean

// 字面量的形式聲明
var flag = false
console.log(flag) // false

// 實例化的形式聲明
var flag = new Boolean(false)
console.log(flag) // false
複製代碼

注意:\color{red}{只有兩個值 true 和 false}spa

1-四、undefined

Undefined 類型只有一個值,即 undefined。\color{red}{當聲明的變量未初始化時,該變量的默認值是 undefined。}3d

1-4-一、聲明

var num
console.log(num)
複製代碼

1-4-二、另外幾種值爲 undefined 的狀況

  • 經過點語法訪問的時候(對象屬性)
  • 經過下標訪問的時候(數組)
  • 不指定函數的返回值時

\color{red}{注意:}

var oTemp;

alert(typeof oTemp);  //輸出 "undefined"
alert(typeof oTemp2);  //輸出 "undefined"
複製代碼

前面的代碼對兩個變量輸出的都是 "undefined",即便只有變量 oTemp2 從未被聲明過。若是對 oTemp2 使用除 typeof 以外的其餘運算符的話,會引發錯誤,由於其餘運算符只能用於已聲明的變量上。
複製代碼

1-五、null

null 類型只有一個值,即 null。指針

console.log(null == undefined) // true
console.log(null === undefined) // false

console.log(null == null) // true
console.log(null == null) // true
複製代碼

\color{red}{null\ 自身跟自身相等,undefined\ 類型是\ null\ 的子類}

1-五、Symbol

Symbol 是 es6 新增的一種基礎數據類型,是用來描述一個\color{red}{惟一性}的值。 Symbol(query: any): symbol query 對當前 Symbol 的描述,便於代碼的閱讀

1-5-一、聲明方式

var symbol1 = Symbol('symbol')
var symbol2 = Symbol('symbol')

console.log(symbol1 === symbol2) // false
console.log(symbol1 === symbol2) // false
複製代碼

1-5-二、用處

  • 能夠用來聲明一個常量
  • 能夠用作對象的屬性,可是不能被for-in, Object.keys()等訪問到,也就是不可枚舉的
  • 使用Symbol定義類的私有屬性/方法

二、引用數據類型

引用數據類型包含如下 \color{red}{4} 中:

  • Object 對象
  • String 對象
  • Boolean 對象
  • Number 對象

以上對象的詳細解析請參考 w3school

三、如何判斷基礎數據類型與引用數據類型之間

3-一、基礎數據類型能夠經過 typeof 來判斷

var num = 12
console.log(typeof num) // number

var str = 'hello'
console.log(typeof str) // string

var flag = true
console.log(typeof flag) // boolean

var un
console.log(typeof un) // undefined

var nul = null
console.log(typeof nul) // object

var fun = function () {}
console.log(typeof fun) // function

var obj = new Object()
console.log(typeof obj) // object

var arr = [1, 2]
console.log(typeof obj) // object
複製代碼

由上可知:\color{red}{ typeof 除了 null 之外其它的基本數據類型均可以判斷,還產生了一種新的數據類型 function }

3-二、引用數據類型能夠經過 instanceof 來判斷 (實現原理是經過原型鏈)

var obj = new Object()
console.log(obj instanceof Object) // true

var str = new String('hello')
console.log(str instanceof String) // true

var arr = [1, 2]
console.log(arr instanceof Array) // true

var num = 1
console.log(num instanceof Number) // false
複製代碼

總結:\color{red}{ typeof、instanceof 都不能準確的判斷出具體的類型 }

四、基礎數據類型與引用數據類型之間的區別

4-一、 基礎數據類型與引用數據類型之間的區別主要體如今在內存中的存儲。

咱們先來看一個例子,思考一下答案是什麼

var num1 = 10
var num2 = num1

num2 = 20
console.log(num1, num2)

var person1 = {name: 'Tom'}
var person2 = person1

person2.name = "Kail"
console.log(person1, person2)
複製代碼

答案:

10 20
{name: 'Kail'} {name: 'Kail'}

能夠看出 num1 不會受到 num2 的影響,person1 會受到 person2 的影響。
複製代碼

總結:\color{red}{引用數據類型在內存中的棧中存儲的是地址(指針),基礎數據類型存儲的是值。因此在用引用數據類型直接賦值時,會直接影響的源數據。}

4-二、淺拷貝、深拷貝

淺拷貝、深拷貝的出現就是爲了解決引用數據類型賦值時,產生相互影響的問題
複製代碼

4-2-一、淺拷貝

淺拷貝\color{red}{只能修復第一層屬性的值不爲引用數據類型的屬性,}仍是不能完全解決多層引用數據類型之間的嵌套。

var person1 = {name: 'Tom'}
var person2 = Object.assign({}, person1)

person2.name = "Kail"
console.log(person1, person2) // {name: "Tom"} {name: "Kail"}


var person1 = {targe: {name: 'Tom'}}
var person2 = Object.assign({}, person1)

person2.targe.name = "Kail"
console.log(person1, person2) // {targe: {name: 'Kail'}} {targe: {name: 'Kail'}}
複製代碼

4-2-二、深拷貝

深拷貝跟層級無關

var person1 = {name: 'Tom'}
var person2 = JSON.parse(JSON.stringify(person1))

person2.name = "Kail"
console.log(person1, person2) // {name: "Tom"} {name: "Kail"}


var person1 = {targe: {name: 'Tom'}}
var person2 = JSON.parse(JSON.stringify(person1))

person2.targe.name = "Kail"
console.log(person1, person2) // {targe: {name: 'Tom'}} {targe: {name: 'Kail'}}
複製代碼

五、類型之間的轉換

5-一、 + (字符串鏈接符,加號運算符)只要有一邊爲字符串或者爲引用數據類型時另一邊就必須轉換爲字符串才能夠作運算;只有兩邊都是純數字時才作加法

var log = console.log

log(1 + 2)          // 3
log(1 + '2')        // '12'

log(1 + true)       // 2
log('1' + true)     // '1true'

log('1' + undefined)  // '1undefined'
log(1 + undefined)  // NaN

log('1' + null)  // '1null'
log(1 + null)  // 1

log(1 + [])         // '1'
log(1 + [2])        // '12'
log(1 + [2, 3])     // '12,3'
log(1 + [{count: 2}]) // '1[object Object]'
log(1 + [{count: 2}, 2, true]) // '1[object Object],2,true'

log(1 + {})         // '1[object Object]'
log(1 + {count: 2}) // '1[object Object]'
複製代碼

分析:

一、undefined 轉換成數字時爲 NaN 
二、null 轉換成數字時爲 0
三、空數組轉換爲空字符串
四、非空數組轉換爲字符串,按照每一個元素來轉換成字符串,而後將其結果以逗號的形式拼接起來
五、對象轉換成字符串都爲 '[object Object]'
複製代碼

5-二、 算術運算符(除 + 以外),都會將兩邊轉換成數字來運算,

var log = console.log

log(2 * 2)          // 4
log(2 * '2')        // 4
log('2' * '2')      // 4
log(2 * null)       // 0
log(2 * undefined)  // NaN
log(2 * [1])         // 2
log(2 * [1, 2])     // NaN
log(2 * {a: 1})     // NaN

log(2 / 2)          // 1
log(2 / '2')        // 1
log(2 / null)       // Infinity
log(2 / undefined)  // NaN
log(2 / [1])         // 2
log(2 / [1, 2])     // NaN
log(2 / {a: 1})     // NaN
複製代碼

5-三、 比較運算符,都會將兩邊轉換成數字來運算,(當兩邊爲字符串時除外,此時會利用字符的 Unicode 編碼來比較大小),特殊狀況(以下)

log(2 > 2)          // false
log(2 > '1')        // true
log(2 > null)       // true
log(2 > [1])        // true
log(2 > {a: 1})     // false
log('a' > 2)      // false
log('abc' < 'b')    // true

// 特殊狀況
log(undefined == undefined)  // true
log(undefined === undefined) // true

log(null == null)        // true
log(null === null)       // true

log(undefined == null)   // true
log(undefined === null)  // false

log(NaN == NaN)          // false
log(NaN === NaN)         // false
複製代碼

5-四、 邏輯非隱式轉換與關係運算符隱式轉換搞混淆

log([] == 0)    // true     [].valueOf().toString = '' Number('') = 0
log(![] == 0)   // true     ![] = false Number(false) = 0    
log([] == [])   // false    地址不同
log(![] == [])  // true     ![] = false Number(false) = 0    [].valueOf().toString = '' Number('') = 0
log(!{} == {})  // false    !{} = false Number(false) = 0    {}.valueOf().toString = '[object Object]' Number('[object Object]') = NaN
log({} == {})   // false    地址不同
複製代碼

5-四、類型轉換總結表

type Number String Boolean
Number 原值轉換 原值轉換 1: 0-> false -0 -> false
2: 其它數值都爲true
String 1: 所有由數字組成的字符串,正常轉換;
2: 空字符串爲0;
3: 其它爲NaN
原值轉換 1:空字符串爲false;
2: 其它爲true
Boolean false -> 0 true -> 1 原值轉換
null 0 '' false
undefined NaN 原值轉換 false
Object NaN '[object Object]' true
Array 1:[] 轉換爲 0([].valueOf().toString() = '' Number('') = 0)
2: 只有一個元素時,就按這個元素的類型轉換成 Number([undefined] 除外,轉換爲 0)
3: 其它狀況爲 NaN
將每一個元素轉換成字符串以逗號的形式拼接 true
function NaN 將函數直接變成字符串輸出 true
Symbol var b = Symbol('測試類型轉換')
Number(b)
Uncaught TypeError: Cannot convert a Symbol value to a number
var b = Symbol('測試類型轉換')
String(b)
"Symbol(測試類型轉換)"
true

【隨手筆記,感謝閱讀,不對之處請指教,謝謝】

相關文章
相關標籤/搜索