Vue原始碼中為什麼要const _toStr = Object.prototype.toString?

今晚的雨停了發表於2019-03-03

在vue的原始碼中,vue/src/shared/util.js檔案中存放的是一些方法。其中作者用了Object.prototype.toString這個方法來判斷型別,但是並沒有直接用,而是單獨儲存在一個變數:

const _toStr = Object.prototype.toString
複製程式碼

那麼為什麼要這麼做呢?

先說下判斷型別。眾所周知,typeof在判斷物件時不能正確判斷Null,並且不能識別出Array,但在判斷基礎型別時是沒問題的。所以尤大也寫了:

export function isPrimitive (value: any): boolean %checks {
  return (
    typeof value === `string` ||
    typeof value === `number` ||
    // $flow-disable-line
    typeof value === `symbol` ||
    typeof value === `boolean`
  )
}
複製程式碼

判斷Object也做了區分,isObject和isPlainObject :

export function isObject (obj: mixed): boolean %checks {
  return obj !== null && typeof obj === `object`
}

export function isPlainObject (obj: any): boolean {
  return _toString.call(obj) === `[object Object]`
}
複製程式碼

到了判斷複雜型別的時候,一般我們用Object.prototype.toString或者是instanceof。如果是前者的話會返回類似`[object Object]`的字串。後者則會判斷一個物件的原型鏈上是否存在一個建構函式。

兩者還有一些不同。Object.prototype.toString.call(1) 和 Object.prototype.toString.call(Number(1))時,返回的都是”[object Number]”,也就是說,它並不能區分原始型別和複雜型別。可見,Object.prototype.toString.call並不像很多教程說的那樣好用。

Object.prototype.toString.call(1)
"[object Number]"

Object.prototype.toString.call(new Number(1))
"[object Number]"
複製程式碼

如果要使用,就需要像尤大一樣,把原始型別單獨拎出來判斷,再去判斷複雜型別,而走到這一步的時候尤大就寫了上面說那行const _toStr。這是因為,toString實在是太容易被重寫了。如果toString被其他人重寫,將會對程式碼中涉及到的部分造成影響,所以就儲存下來防止這種情況發生。

相關文章