你應該知道的JS--類型

數據類型

內置類型

在 JavaScript 中有七種數據類型:算法

  • 空值(null)
  • 未定義(undefined)
  • 布爾值(boolean)
  • 數字(number)
  • 字符串(string)
  • 對象(object)
  • 符號(symbol)

類型檢測

咱們一般是使用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 爲儲存其類型信息函數

  • 000: 對象
  • 010: 浮點數
  • 100: 字符串
  • 110: 布爾
  • 1: 整數 可是對於undefiendnull來講,這兩個值的存儲信息比較特殊,null的全部機器碼全是 0,undefeind-2^30表示,由於null的機器碼全是 0 因此typeofnull看成對象來看,可是用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

  1. 若是存在靜態方法Symbol.hasInstance。則使用他
class Animal {
  static [Symbol.hasInstance](obj){
    if(obj.canEat) return true;
  }
}

let obj = { canEat: true };
alert(obj instanceOf Animal); // true
複製代碼
  1. 大多數構造函數沒有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]
複製代碼

類型轉換

將值從一種類型和另外一種類型一般稱爲類型轉換,下面是他們轉換的規則:

  1. ToString

基本類型值的字符串化規則是:

  • undefined -> undefined
  • Null -> null
  • Boolean -> true返回"true", false返回false
  • Number -> 'number'
  • Symbol -> throw typeError

對普通對象來講,除非本身定義[Symbol.toStringTag]方法,不然toString()會返回內部屬性[[class]]的值。固然若是對象本身有toString方法,則會調用該方法使用其返回值

  1. ToNumber

基本類型值的數字化規則是:

  • undefined -> NaN
  • Null -> +0
  • Boolean -> true返回1,false返回+0
  • Symbol -> throw TypeError

對象應用如下步驟:

  1. 調用ToPrimitive轉換成基本類型值
  2. 以後再調用ToNumber

字符串: ToNumber 應用在字符串上會去檢測是否數字,若是不是數字那麼結果是NaN

  1. ToBoolean

基本類型值的布爾化規則是:

  • undefiend -> false
  • Null -> false
  • Number -> 除了+0, -0, NaN,其餘返回true
  • String -> 除了" "返回false其餘返回false
  • Symbol -> true
  • Object -> true
  1. ToPrimitive

當咱們須要將對象類型轉換成基本類型的時候,使用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 嘗試查找並調用三個對象方法

  1. 調用obj[Symbol.toPrimitive](hint)若是方法存在
  2. 不然,若是提示是string,嘗試obj.toString()obj.valueOf()不管存在
  3. 不然,若是提示是numberdefault,嘗試obj.valueOf()obj.toString(),不管存在

寬鬆相等(==)

ES 規範定義了抽象相等比較算法類定義==運算符,該算法涵蓋了全部的類型組合,以及他們 進行強制類型轉換的方式

  1. 若是 x 或 y 中有一個爲 NaN,則返回 false;
  2. 若是 x 與 y 皆爲 null 或 undefined 中的一種類型,則返回 true(null == undefined // true);不然返回 false(null == 0 // false);
  3. 若是 x,y 類型不一致,且 x,y 爲 String、Number、Boolean 中的某一類型,則將 x,y 使用 ToNumber 函數轉化爲 Number 類型再進行比較;
  4. 若是 x,y 中有一個爲 Object,而另外一個爲字符串, 數字或符號, 則首先使用 ToPrimitive 函數將其轉化爲原始類型,再進行比較。
相關文章
相關標籤/搜索