引自
我的個人部落格,原文連結: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]
apply
是Function
物件的一個方法,可以更改函式執行上下文,意思是執行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 協議》,轉載必須註明作者和本文連結