在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被其他人重寫,將會對程式碼中涉及到的部分造成影響,所以就儲存下來防止這種情況發生。