在 JavaScript 中有七種數據類型:算法
咱們一般是使用typeof
運算符來查看值的類型,他返回的是類型的字符串值。bash
typeof undefiend === 'undefined' // true
typeof true === 'boolean' // true
typeof 42 === 'number' // true
typeof "42" === 'string' // true
typeof { life: 42 } === 'object' // true
typeof Symbol() === 'symbol' // true
複製代碼
以上六種基本類型均有同名的字符串之與之對應。而null
類型不在此列,他比較特殊,typeof 對他的處理有問題ide
typeof null === 'object' // true
複製代碼
這是由於 js 在底層儲存變量的時候,會在變量的機器碼的低位 1~3 爲儲存其類型信息函數
undefiend
和null
來講,這兩個值的存儲信息比較特殊,null
的全部機器碼全是 0,undefeind
用-2^30
表示,由於null
的機器碼全是 0 因此typeof
把null
看成對象來看,可是用instanceOf
進行判斷的話null instanceof null // TypeError: Right-hand side of 'instanceof' is not an object
複製代碼
null 被直接判斷爲不是對象, 咱們還能夠經過instanceOf
來判斷一個實例是否屬於某種類型。例如ui
class animal{}
let cat = new animal();
cat iinstanceOf animal // true
複製代碼
也支持內置類型spa
let arr = [1, 2, 3];
alert(arr instanceOf Array); // true
alert(arr instanceOf Object); // true
複製代碼
注意: arr
也屬於Object
,這是由於 Array 原型繼承Object
之因此會這樣,就涉及到instanceOf
的原理了。檢查類型是否在實例的原型鏈上。 obj instanceOf Class
的算法大體以下prototype
Symbol.hasInstance
。則使用他class Animal {
static [Symbol.hasInstance](obj){
if(obj.canEat) return true;
}
}
let obj = { canEat: true };
alert(obj instanceOf Animal); // true
複製代碼
Symbol.hasInstance
。在這種狀況下,檢查class.prototype
是否等於obj
原型鏈中的原型之一。obj.__proto__ === class.prototype
onj.__proto__.__proto__ === class.prototype
複製代碼
在繼承的狀況下:3d
class Animal {}
class Rabbit extends Animal {}
let rabbit = new Rabbit();
alert(rabbit instaneOf Animal); // true
// rabbit.__proto__ === Rabbit.prototype
// rabbit.__proto__.__proto__ === Animal.prototype
複製代碼
固然這種方法也會有原型鏈斷裂的風險,例如:code
function Rabbt(){}
let rabbit = new Rabbit();
Rabbit.prototype = {};
console.log(rabbit instanceOf Rabbit); // false
複製代碼
如今咱們一般使用Object.prototype.toString.call
方法來檢測的類型:cdn
let s = Object.prototype.toString;
s.call(123); // [object, Number]
s.call(null); // [object null]
s.call(alert); // [object Function]
複製代碼
固然咱們也能夠去自定義一個toString
行爲
let user = {
[Symbol.toStringTag]: 'user'
}
consle.log({}.toString.call(user)); // [object, User]
複製代碼
將值從一種類型和另外一種類型一般稱爲類型轉換,下面是他們轉換的規則:
基本類型值的字符串化規則是:
undefined
null
true
返回"true"
, false
返回false
throw typeError
對普通對象來講,除非本身定義[Symbol.toStringTag]
方法,不然toString()
會返回內部屬性[[class]]
的值。固然若是對象本身有toString
方法,則會調用該方法使用其返回值
基本類型值的數字化規則是:
NaN
+0
true
返回1
,false
返回+0
throw TypeError
對象應用如下步驟:
ToPrimitive
轉換成基本類型值ToNumber
字符串: ToNumber 應用在字符串上會去檢測是否數字,若是不是數字那麼結果是NaN
基本類型值的布爾化規則是:
false
false
+0, -0, NaN
,其餘返回true
" "
返回false
其餘返回false
true
true
當咱們須要將對象類型轉換成基本類型的時候,使用ToPrimitive
算法,將其轉換爲基本類型 該算法容許咱們用特殊的對象方法自定義轉換,這取決於上下文的提示 提示分爲三種
string
: 當一個操做指望一個字符串時,用於對象到字符串的轉換alert(obj)
// 使用對象當鍵名
another[obj] = 123 // obj 爲 [object object]
複製代碼
number
: 當一個操做須要一個數字的時候,用於對象到數字的轉換,例如數學公式let num = Number(obj);
let n = +obj;
let delta = date1 - date2;
let greater = user1 > user2
複製代碼
default
: 在少數狀況下,操做不肯定指望的類型的時候,例如+
運算符能夠是拼接字符串或者數學公式相加或者當一個對象==
與字符串,數字或符號進行比較時。let total = car1 + car2
// obj == string/number/symbol
if(user == 1){ ... }
複製代碼
爲了進行轉換,JavaScript 嘗試查找並調用三個對象方法
obj[Symbol.toPrimitive](hint)
若是方法存在string
,嘗試obj.toString()
和obj.valueOf()
不管存在number
或default
,嘗試obj.valueOf()
和obj.toString()
,不管存在ES 規範定義了抽象相等比較算法類定義==
運算符,該算法涵蓋了全部的類型組合,以及他們 進行強制類型轉換的方式