JavaScript基本型別總結

wj2015發表於2020-12-21

JavaScript基本型別總結

引自

我的個人部落格,原文連結:JavaScript基本型別總結

背景

最近仔細看了看Javascript的變數相關章節,包括網道阮一峰大神寫的 JavaScript教程,以及被譽為JS聖經的《JavaScript權威指南》,故對變數的基礎型別做一個總結

變數有什麼型別?

JS中的資料型別總體分為兩類:原始型別和物件型別

原始型別

包括數字、字串、布林值、null、undefined

物件型別

除了原始型別,其他都是物件型別,Object(普通物件)、Function(函式)、Array(陣列)

PS: 雖然字元和數字也能通過物件的方式呼叫方法,但是這只是JS自動進行的包裝物件,比如:

'1,2'.split();// '1,2' 會被轉換為 String('1,2')
var a = 3.1415926;
var b = a.toFixed(2)// a 會被轉換為 Number(a)
var c = new Number(111); c === 111// false 包裝物件與原屬性不全等
Number(111) === 111 // true, Number(111) 是顯示轉換的意思,結果是 111,所以全等

var str = 'test';
str.number = 10;// 包裝String物件
console.log(str.number);// undefined,注意這個地方,包裝物件的生命週期只在那一個語句,下一個語句就沒了

var arr = [];
arr.number = 123;
console.log(arr.number);// 123,這裡是因為 [] 本來就是物件,與包裝物件不同

包裝物件的詳解可以參考如下部落格:blog.csdn.net/lhjuejiang/article/d...

型別轉換

由於JS是一個弱型別的語言,所以在不同資料型別的資料進行比較或者操作的時候,需要進行型別轉換,型別轉換分強制轉換(也稱顯式轉換)以及自動轉換(也稱隱式轉換)

強制轉換

使用 Number() String() Boolean() 等建構函式進行強制轉換,也相當於顯示新增了包裝物件,相比 parseInt(),parseFloat() 等輔助函式更加嚴格

Number('1') // 1
Number(true) // 1
Number(false) // 0
Number('1.2e8') // 120000000 PS:科學計數法
Number('0b1001')// 9 PS:二進位制
Number('0xF') // 15 PS:十六進位制
Number('0o777') // 511 PS:八進位制
Number('1x') // NaN

// valueOf 用於返回物件自身,預設 return this,如果返回物件則呼叫原物件的 toString() 方法,如果 toString() 依舊返回物件,則報錯無法轉換
Number({
    valueOf: function() {
        return 123;
    }
}) // 123
Number({
    valueOf: function() {
        return {}
    },
    toString: function() {
        return {}
    }
})// 報錯 Uncaught TypeError: Cannot convert object to primitive value

String(true) // 'true'
String(1.) // '1'
String(1.1) // '1.1'
String(-0) // '0'
String(-Infinity) // -Infinity
String(Infinity) // Infinity

Boolean('') // false
Boolean(0) // false
Boolean(null) // false
Boolean(NaN) // false
Boolean(undefined) // false
Boolean([]) // true PS:除了上邊的,其他轉出來都是 true
Boolean({}) // true

自動轉換

JS在不同型別資料互相運算時,非布林值求布林值,非數值型別使用 + – * / ,會自動根據場景呼叫相應的強制轉換函式,既能轉為字元又能轉為數字時,優先數字

自動轉Boolean

在需要用到布林判斷時,會導致此轉換,比如 (if/else、三目運算子之類的)

if (
    '' == false &&
    null == false &&
    undefined == false &&
    0 == false &&
    NaN == false
){
    console.log(111);// true
}
[] ? 111 : 000 // 111
自動轉數字

涉及 + – * / 等操作會轉換為數字

1 + '2' // 3
1 + 's' // NaN
true + 1 // 2
'c' - 1 // NaN
自動轉字元

字元 + 非字元 會被轉換為字串

'abc' + 1 // abc1
'1' + 0 // 10
'5' + undefined // 5undefined
'5' + function(){} // 5function(){}

如何檢查變數型別

JavaScript是一個弱型別語言,我們可以用內建的三種方法判斷一個值到底屬於什麼型別

  • typeof 運算子
  • instanceof 運算子
  • Object.prototype.toString 方法

typeof判斷變數型別的各種情況

typeof 123 // number
typeof '123' // string
typeof false // boolean

f = function() {}
typeof f // function
typeof undefined // undefined
typeof xxxxx // 未定義變數不報錯,返回 undefined

typeof {} // object
typeof window // object
typeof [] // object,陣列的typeof是object
typeof null // object,null的typeof也是object

需要注意的點:陣列、null 呼叫 typeof 都是 object。因為在JS中,陣列本質上是一種特殊的物件,而null是因為最開始的JS把null作為物件的一種特殊值,為了向前相容,就一直 typeof null === ‘object’ 了

instanceof 通過原型鏈判斷資料型別

instanceof 返回一個 Boolean,表示物件的原型鏈中是否存在某個建構函式(原始定義:物件是否為某個建構函式的例項)。

關於原型鏈,這裡簡單提及下,一個物件的 prototype 都指向其建構函式的 prototype,其中有一個方法 Object.getPrototypeOf 返回物件的原型,最終的最終都會指向 Object,而 Object.prototype = null,整個原型鏈到了盡頭,原型鏈的更為詳細的介紹可點選:參考部落格

一些例項如下:

[] instanceof Array // true 因為原型鏈裡有 Array 這個建構函式
[] instanceof Object // true 因為原型鏈裡有 Object 這個建構函式
Array instanceof Object // true,因為Array是一個特殊的物件
[] instanceof null // 報錯,Right-hand side of 'instanceof' is not an object,因為null不是個物件

var func = function() {}
func instanceof Function // true,原型鏈中有Function
func instanceof Object // true,Function的原型是 Object
Function instanceof Object // true,函式是一個特殊物件

Object.prototype.toString()

toString() 用於返回一個物件的字串形式,用於在自動型別轉換時得到想要的字元形式。一些樣例具體如下:

var obj = {};
obj.toString() // [object Object]
var obj2 = {name: 'xxx'};
obj2.toString = function() {
    return 'Hello '+this.name
}
obj2.toString() // Hello xxx
obj2 == 'Hello xxx' // true

var obj3 = []
obj3.toString() // '' 空字串,因為陣列是空的
var obj4 = [1, 2, 3]
obj4.toString() // '1,2,3'

由於物件的 toString 可以被過載,如果要用於型別判斷的話,需要用到 Object.prototype.toString.apply(obj) 的方式,顯示格式 [object 建構函式],比如 [object Object], [object Number], [object String],[objct Function],不過有個問題是無法精確判斷 字元物件 和 字串,因為返回都是 [object String]

applyFunction 物件的一個方法,可以更改函式執行上下文,意思是執行 Object.prototype.toString 函式,但是執行過程中的 this 指向外部注入的 obj,如果還是看不明白可以參考博主之前寫的另外一篇部落格 JS中Function.apply() 的騷操作

Object.prototype.toString.apply({}) // [object Object]
Object.prototype.toString.apply([]) // [object Array]
Object.prototype.toString.apply('') // [object String]
Object.prototype.toString.apply(String('')) // [object String]
Object.prototype.toString.apply(123) // [object Number]
Object.prototype.toString.apply(NaN) // [object Number]

Object.prototype.toString.apply(String) //[object Function]
Object.prototype.toString.apply(function(){return 111}) //[object Function]

Object.prototype.toString.apply(undefined)// [object Undefined]
Object.prototype.toString.apply(null) // [object Null]
Object.prototype.toString.apply(true) // [object Boolean]

總結

變數型別是JS的基礎之一,也是平時很容易忽視的地方,稍不注意就容易產生莫名其妙的BUG,特此總結

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章