JS基本觀念:typeof vs instanceof

Charles Huang
6 min readSep 13, 2019

在寫程式時難免會要對變數型別做判斷,舉例像是在寫api時,這時要把使用者想得越機車越好,因為你不能預料到他會不會臨機一動就給你來個你沒想過的參數(因為我自己也是XD),所以這邊來聊一下在 javascript 裡面常用到的兩個功能,typeof 以及 instanceof。

1. typeof

typeof 就是用來判斷參數是什麼型別,用法很簡單,就typeof A

回傳值基本上就是常見的js data type:

"number", "string", "boolean", "object", "function", "undefined", "symbol", "bigint" 

以下來看些簡單例子吧!

// Number
typeof 10
typeof 3.14
typeof Infinity
typeof typeof NaN
// String
typeof ''
typeof 'abc'
// Boolean
typeof true
typeof !!(1)
// Undefined
typeof undefined
typeof declaredButUndefinedVariable //宣告但沒賦值
typeof undeclaredVariable //未宣告
// Object
typeof {a: 1}
typeof null
typeof new Date()
typeof new RegExp()
// 以下用法比較少見,但他的確會被判定成object
typeof new Boolean(true)
typeof new Number(1)
typeof new String('abc')
// function
typeof function() {}
typeof Math.sin
typeof class C {}

小結

  • 對primitive type(string, number等object外)類型的判斷回傳值都挺正確的,除了null外
  • 對於object,除了function外,其他一律回傳object
  • 對於null,回傳object
  • 對於function,回傳function

至於為何null會這麼特別

In the first implementation of JavaScript, JavaScript values were represented as a type tag and a value. The type tag for objects was 0. null was represented as the NULL pointer (0x00 in most platforms). Consequently, null had 0 as type tag, hence the "object" typeof return value. (reference)

2. instanceof

instanceof 是用來判斷 A是否為B的實例,比較的是原型(prototype)。用法:

object instanceof constructor// object: The object to test.
// constructor:Function to test against

故若constructor.prototype存在於object的原型鍊(prototype chain)裡面,則回傳true,否則false。

下面來舉個例子說明吧!

function C() {}
function D() {}

var o = new C();

// true, 因為C在o的原型鍊內 ; o.__proto__ === C.prototype
o instanceof C;

// false, 因為 D.prototype 不存在在 o 的原型鍊
o instanceof D;
// true 因為object存在於o的原型鍊
// o.__proto__.__proto__ === Object.prototype
o instanceof Object;

這邊我們來把o的原型鍊給畫出來會更容易理解!

從原型鍊中可以看到,o指到C.prototype而又間接的指到Object.prototype,所以依照instanceof的規則,o是Object的一個實例。依此類推,類似new Date() , new RegExp()等等也會形成一條類似的原型鍊。因此,instanceof只能用來判斷兩個比較對象是否屬於實例關係,無法明確指出具體屬於哪種類型。

小結

  • 畫出原型鍊(prototype chain)吧!一切就會很明瞭啦。

toString()

延續上面提到的instanceof無法明確指出屬於哪種類型,我們可以利用Object原生提供的toString()方法來得到類型。使用callapply來呼叫該方法可以得到呼叫者的類型,格式為[object xxx],xxx包含了String、Number、Boolean、Undefined、Null、Function、Date、Array、RegExp、Error、HTMLDocument 等,基本上所有類型都能靠這種方法找到。

Object.prototype.toString.call('') ;   // [object String]
Object.prototype.toString.call(1) ; // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(Symbol()); //[object Symbol]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]

--

--

Charles Huang

Made in Taiwan的後端工程師,擅長nodejs做後端開發。相信分享與交流可以讓世界更美好,加上自己有點金魚腦,所以開始了寫些有的沒的之路XD