關於JS類型判斷的思考

初衷

寫這篇文章的初衷是來源於JS基礎問題-類型判斷,僅看成鞏固下知識。javascript

咱們常說學習一個知識點要學會延伸思考,點畫線,線繪面,造成本身的知識體系。java

一個小小的類型判斷其實也能夠拓展出不少知識點。node

What: 什麼是類型?

計算機程序的運行須要對值進行操做,而在編程語言中,可以表示並操做的值的類型稱爲數據類型。git

編程語言最基本的特徵就是支持多種數據類型。github

Who:JS有哪幾類數據類型,以及分別是什麼?

JS有兩類數據類型:原始類型(primitive type)和對象類型(object type)。web

原始類型

  • number
  • string
  • boolean
  • undefined
  • null
  • symbol
  • Bigint

指的注意的是null確實屬於基本類型,由於有時它容易被誤認爲是對象類型。編程

typeof null === 'object' // 這應該算語言的一個bug
複製代碼

typeof null 感興趣的能夠看這個討論segmentfault

對象類型

  • object

實際上JS還有不少特殊的對象子類型,咱們能夠稱之爲複雜基本類型。數組

好比說:編程語言

  • String
  • Number
  • Boolean
  • Function
  • Array
  • Date
  • Regexp
  • Error
  • Object
  • Buffer
  • Map
  • Set
  • WeakSet
  • WeakMap

這裏又會有一個思考:基本數據類型與引用數據類型的區別,常見於函數的入參。

基本數據類型它是按值訪問。

const a = 10;
let b = a;
b = 20;
複製代碼

引用類型數據在棧內存中保存的其實是對象在堆內存中的引用地址(「指針」)。經過這個引用地址能夠快速查找到保存中堆內存中的對象。

const obj1 = new Object();

const obj2 = obj1;

obj2.name = "我有名字了";
複製代碼

Why:爲何咱們須要本身實現JS類型判斷?

由於JS自帶的類型判斷方法不能知足咱們的需求。

JS自帶的類型判斷方法

  • typeof
console.log(typeof '11') // string
console.log(typeof 11) // number
console.log(typeof true) // boolean
console.log(typeof undefined) // undefined
console.log(typeof null) // object, 算語言的bug,實際上該方式並不能判斷出null
console.log(typeof Symbol('test')) // symbol
console.log(typeof /.?/gi) // object
console.log(typeof []) // object
console.log(typeof new Date()) // object
複製代碼

你會發現typeof只能判斷基本數據類型(null仍是一個特例,須要特殊處理),不適用於判斷對象類型,由於它沒法判斷出具體的子類型。

下面幾個簡單題目測試下是否掌握了typeof用法。

var y = 1, x = y = typeof x;
console.log(x) // undefined
複製代碼
var foo = {
    bar: function() { return this.baz; },
    baz: 1
  };
  (function(){
    return typeof arguments[0]();//"undefined"
  })(foo.bar);
複製代碼
  • instanceof

instanceof 主要的做用就是判斷一個實例是不是其父類型或者祖先類型的實例。它是基於原型鏈的查找。

let person = function () {
}
let nicole = new person()
nicole instanceof person // true
複製代碼

咱們看下面這個demo你就知道爲何有些場景下不能用instanceof來判斷數據類型了。

const arr = []
const obj = {}
const func = function() {}

console.log(arr instanceof Array)  // true
console.log(arr instanceof Object) // true
console.log(obj instanceof Object) // true
console.log(func instanceof Object) // true
複製代碼

How:如何實現JS類型判斷?

下面咱們看看lodash是如何進行JS類型判斷的。

  • _.isObjectLike(value) 類對象
/** * Checks if `value` is object-like. A value is object-like if it's not `null` * and has a `typeof` result of "object". * * isObjectLike({}) * // => true * * isObjectLike([1, 2, 3]) * // => true * * isObjectLike(Function) * // => false * * isObjectLike(null) * // => false */
function isObjectLike(value) {
  return typeof value === 'object' && value !== null
}

export default isObjectLike
複製代碼
  • _.isArguments(value) 類 arguments 對象
const toString = Object.prototype.toString

// Gets the `toStringTag` of `value`.
// 這個方法很重要
function getTag(value) {
  if (value == null) {
    return value === undefined ? '[object Undefined]' : '[object Null]'
  }
  return toString.call(value)
}

function isArguments(value) {
  return isObjectLike(value) && getTag(value) == '[object Arguments]'
}
複製代碼
  • _.isArrayLike(value)
// 檢查 value 是否爲有效的類數組長度。
function isLength(value) {
  return typeof value === 'number' &&
    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER
}


function isArrayLike(value) {
  return value != null && typeof value !== 'function' && isLength(value.length)
}
複製代碼
  • _isBoolean()
// isBoolean(null) false
function isBoolean(value) {
  return value === true || value === false ||
    (isObjectLike(value) && getTag(value) == '[object Boolean]')
}
複製代碼

這裏就不詳細列舉,感興趣強烈推薦閱讀lodash源碼

關於類型還涉及的知識點有

ps: 感興趣的關注個人公衆號。

相關文章
相關標籤/搜索