国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Lodash 是如何做類型檢測的

keke / 1749人閱讀

摘要:與之前的類似,利用構造函數創建的字符串是一個所以檢測字符串,除了基本字符串以外還要注意字符串對象。也就是說該對象由構造函數創建,或者為。

原文:https://fatge.github.io/2019/...
歡迎Star:https://github.com/FatGe/FatG...

JS 的基本數據類型有 NumberStringBooleanSymbolNullUndefined,六種數據類型。一種引用類型 object

基本數據類型 Number

數值,根據 ECMAScript 標準,JavaScript 中只有一種數字類型:基于 IEEE 754 標準的雙精度 64 位二進制格式的值(-(263 -1) 到 263 -1)。它并沒有為整數給出一種特定的類型

除了能夠表示浮點數外,還有一些帶符號的值:+Infinity-InfinityNaN (非數值,Not-a-Number)。

對應 lodash 中的檢測函數有

isNumber 檢查 value 是否是原始 Number 數值型 或者 對象;

isInteger 檢查 value 是否為一個整數;

isNaN 檢測 value 是否為 NaN

isFinite 檢測 value 是否是原始有限數值。

isNumber
function isNumber(value) {
  return typeof value == "number" ||
    (isObjectLike(value) && getTag(value) == "[object Number]")
}

typeof 操作符可以返回一個字符串,表示未經計算的操作數的類型。對于 Number、String、Boolean、Undefined、String 可以很明確的得到它的類型。

那么 lodash 為什么還要添加 (isObjectLike(value) && getTag(value) == "[object Number]")

原因在于,JS 中也允許我們以如下形式創建一個數值

const value = new Number(1)
console.log(value) // log 1
console.log(typeof value) // log "object"

這時,單單只是使用 typeof 操作符就沒法判斷 value 的類型是否為數值。所以要結合以下兩個函數來判斷,value 是否為 object 然后再通過過 toString() 來獲取每個對象的類型。

function getTag(value) {
  if (value == null) {
    return value === undefined ? "[object Undefined]" : "[object Null]"
  }
  return Object.prototype.toString.call(value)  
}

function isObjectLike(value) {
  return typeof value == "object" && value !== null
}
Object.prototype.toString.call 每個對象都有一個toString()方法,當該對象被表示為一個文本值時,或者一個對象以預期的字符串方式引用時自動調用。
isInteger
function isInteger(value) {
    return 
        typeof value == "number" 
        && value == toInteger(value);
}

檢查 value 是否為一個整數,判斷是否 value 的類型是否為數值,并且是否與 Int 型相同。其取整過程如下

function toInteger(value) {
    var result = toFinite(value),
        remainder = result % 1;

    return result === result ? 
        (remainder ? result - remainder : result) : 0;
}
isNaN

檢查 value 是否是 NaN

function isNaN(value) {
    return isNumber(value) && value != +value;
}

與 ES 2015 的 isNaN 不同的是,對于 undefined{},原生的結果是 true,而 lodashfalse。這是因為如果isNaN函數的參數不是Number類型, isNaN函數會首先嘗試將這個參數轉換為數值,然后才會對轉換后的結果是否是NaN進行判斷。

// js native isNaN
var isNaN = function(value) {
    var n = Number(value);
    return n !== n;
};

但是無論是 ES 2015 還是 lodash,它們本質上都是利用 x != x 來判斷 NaN

isFinite

檢查 value 是否是原始有限數值。

function isFinite(value) {
    return typeof value == "number" 
        && nativeIsFinite(value);
}

利用原生的 isFinite 結合 typeof 判斷數字是否為有限值。

String

String 類型用于表示由零或多個16 位Unicode 字符組成的字符序列,即字符串。用于保存可以以文本形式表示的數據非常有用。

值得注意的是,不單單要注意基本字符串,還需要注意字符串對象,字符串字面量 (通過單引號或雙引號定義) 和 直接調用 String 方法(沒有通過 new 生成字符串對象實例)的字符串都是基本字符串。

JavaScript會自動將基本字符串轉換為字符串對象,只有將基本字符串轉化為字符串對象之后才可以使用字符串對象的方法。

與之前的 number 類似,利用構造函數 String 創建的字符串是一個 object

const s_prim = "foo";
const s_obj = new String(s_prim);

console.log(typeof s_prim); // Logs "string"
console.log(typeof s_obj);  // Logs "object"

所以檢測字符串,除了基本字符串以外還要注意字符串對象。

function isString(value) {
  const type = typeof value
  return 
    type == "string" || 
        (type == "object" 
             && value != null 
             && !Array.isArray(value) 
             && getTag(value) == "[object String]")
}

可以利用 typeof 檢測基本字符串,對于模板字符串采用了之前介紹的方案 getTag 來獲取 value 的類型。

Boolean

Boolean 類型是ECMAScript 中使用得最多的一種類型,該類型只有兩個字面值:truefalse。同樣也需要區分基本的 Boolean 類型以及 Boolean 對象。

function isBoolean(value) {
  return 
    value === true || value === false ||
    (isObjectLike(value) 
     && getTag(value) == "[object Boolean]")
}

大部分在之前都已經涉及到了,這里出現了 isObjectLike,那么它是做什么的。

function isObjectLike(value) {
  return typeof value == "object" && value !== null
}

原來只是檢測是否是一個非 null 的對象。

Symbol

ES6 引入了一種新的原始數據類型Symbol,表示獨一無二的值。Symbol 值通過Symbol函數生成。

function isSymbol(value) {
  const type = typeof value
  return type == "symbol" || 
      (isObjectLike(value) && 
       getTag(value) == "[object Symbol]")
}

會發現 (isObjectLike(value) && getTag(value) == "[object Symbol]"),也對 Symbol 對象進行檢測,但是如果直接 new Symbol 會 log 出 TypeError

那么 lodash 為什么要對其進行檢測,原來是創建一個顯式包裝器對象從 ECMAScript 6 開始不再被支持,現在可以利用如下代碼來模擬,雖然沒什么用。

const sym = Symbol("foo");
typeof sym;     // "symbol"
const symObj = Object(sym);
typeof symObj;  // "object"
Undefined

Undefined 類型只有一個值,即特殊的 undefined。在使用 letvar 聲明變量但未對其加以初始化時,這個變量的值就是 undefined

function isUndefined(value) {
    return value === undefined;
}
Null

Null 類型是只有一個值的數據類型,這個特殊的值是 null 。與 undefined 不同的是,它是一個字面量,而 undefined 是全局對象的一個屬性。

從邏輯角度來看,null 值表示一個空對象指針,null 是表示缺少的標識,指示變量未指向任何對象。而這也正是使用typeof 操作符檢測null 值時會返回"object"的原因。

對其的判斷也非常的簡單,只需要

function isNull(value) {
  return value === null
}

當然你也可以使用

console.log(Object.prototype.toString.call(null))
// [object Null]

以上是基本數據類型的判斷,總結一下,主要是利用 typeOf 以及 Object.prototype.toString ,還有一些特殊值的特性。下面開始分析引用類型 Object

引用類型

引用類型的值(對象)是引用類型的一個實例。在ECMAScript 中,引用類型是一種數據結構,用于將數據和功能組織在一起。具體的有 ObjectArrayDateErrorRegExpFunction,還有ES2015 引入 SetMapWeakSetWeakMap

Object

ECMAScript 中的對象其實就是一組數據和功能的集合。它有一個很重要的用途,就是在 JavaScript 中的所有對象都來自 Object;所有對象從Object.prototype繼承方法和屬性,盡管它們可能被覆蓋。即在ECMAScript 中,Object 類型是所有它的實例的基礎。

所以 Lodash 去判斷 value 是否為 Object 時,只使用了 typeOf 操作即可。

function isObject(value) {
  const type = typeof value
  return value != null && 
      (type == "object" || type == "function")
}
Function

Function 構造函數 創建一個新的Function對象。 在 JavaScript 中, 每個函數實際上都是一個Function對象。

function isFunction(value) {
  if (!isObject(value)) {
    return false
  }

  const tag = getTag(value)
  return tag == "[object Function]" || 
          tag == "[object AsyncFunction]" ||
        tag == "[object GeneratorFunction]" || 
          tag == "[object Proxy]"
}

有個問題,typeOf 可以檢測 Function對象的類型為 Function, 那為什么還需要 Object.prototype.toString 呢?

// in Safari 9 which returns "object" for typed arrays and other constructors.
Array

Array 在 ECMAScript 中代表數組,它的每一項可以保存任何類型的數據。

對它的常規檢測就是 Array.isArrayLodash 也是使用這個 API,如果需要 Polyfill 方案的話,可以使用

// plan 1
Object.prototype.toString.call(value) === "[object Array]"
// plan 2
value.constructor === Array

之前還有 value instanceof Array 會什么問題么?

在存在不同全局變量的環境,通過語義 instanceof 檢測數組的時候,value instanceof Array只有當 value 是由該頁面的原始 Array 構造函數創建的數組時才能正常工作。

具體請見,http://web.mit.edu/jwalden/ww...。

Date

ECMAScript 中的 Date 類型是在早期Java 中的java.util.Date 類基礎上構建的。

const nodeIsDate = nodeTypes && nodeTypes.isDate

const isDate = nodeIsDate
  ? (value) => nodeIsDate(value)
  : (value) => isObjectLike(value) && getTag(value) == "[object Date]"

Lodash 分為兩個環境來處理這個問題,如果是 Node 就利用 util.types.isDate(value) 來檢測,如果是在游覽器,就還是通過 Object.prototype.toString 來判斷。

Set

ES2015 提供了新的數據結構 Set。它類似于數組,但是成員的值都是唯一的,沒有重復的值。

const isSet = nodeIsSet
  ? (value) => nodeIsSet(value)
  : (value) => isObjectLike(value) && getTag(value) == "[object Set]"

同樣的還有 Map

const isMap = nodeIsMap
  ? (value) => nodeIsMap(value)
  : (value) => isObjectLike(value) && getTag(value) == "[object Map]"
WeakSet

WeakSet 結構與 Set 類似,也是不重復的值的集合。但是,它與 Set 有兩個區別。

function isWeakSet(value) {
  return isObjectLike(value) && getTag(value) == "[object WeakSet]"
}

也是利用 Object.prototype.toString ,同樣還有 WeakMap

function isWeakMap(value) {
  return isObjectLike(value) && getTag(value) == "[object WeakMap]"
}
Error

當運行時錯誤產生時,Error的實例對象會被拋出。

function isError(value) {
  if (!isObjectLike(value)) {
    return false
  }
    
  const tag = getTag(value)
  return tag == "[object Error]" || 
      tag == "[object DOMException]" ||
    (typeof value.message == "string" && typeof value.name == "string" && !isPlainObject(value))
}

有之前一致的 Object.prototype.toString 依然可以用來判斷對象是否是一個 Error,除此之外,如果對象滿足以下條件,也可以被視為一個 Error

具備 messagename 屬性,且值為 string

是普通對象。 也就是說該對象由 Object 構造函數創建,或者 [[Prototype]]null

那么如何檢測普通對象呢?

function isPlainObject(value) {
  if (!isObjectLike(value) || getTag(value) != "[object Object]") {
    return false
  }
  if (Object.getPrototypeOf(value) === null) {
    return true
  }
  let proto = value
  while (Object.getPrototypeOf(proto) !== null) {
    proto = Object.getPrototypeOf(proto)
  }
  return Object.getPrototypeOf(value) === proto
}

主要是利用 Object.getPrototypeOf() 方法返回指定對象的原型(內部[[Prototype]]屬性的值),同時和 value 本身的 [[Prototype]] 做判斷。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/106178.html

相關文章

  • JavaScript 深拷貝

    摘要:深拷貝是一件看起來很簡單的事情,但其實一點兒也不簡單。我們也可以利用這個實現對象的深拷貝。而是利用之前已經拷貝好的值。深拷貝的詳細的源碼可以在這里查看。大功告成我們雖然的確解決了深拷貝的大部分問題。 js深拷貝是一件看起來很簡單的事情,但其實一點兒也不簡單。對于循環引用的問題還有一些內置數據類型的拷貝,如Map, Set, RegExp, Date, ArrayBuffer 和其他內置...

    zhangwang 評論0 收藏0
  • lodash源碼分析之List緩存

    摘要:在之前的文章中已經介紹過,檢測的是對應的數組在二維數組中的索引,其行為跟一致,不存在于二維數組中時,返回,否則返回索引值。最后將緩存數量減少。 昨日我沿著河岸/漫步到/蘆葦彎腰喝水的地方順便請煙囪/在天空為我寫一封長長的信 潦是潦草了些/而我的心意/則明亮亦如你窗前的燭光/稍有曖昧之處/勢所難免/因為風的緣故 ——洛夫《因為風的緣故》 本文為讀 lodash 源碼的第七篇,后續文章會...

    leon 評論0 收藏0
  • lodash源碼分析之List緩存

    摘要:在之前的文章中已經介紹過,檢測的是對應的數組在二維數組中的索引,其行為跟一致,不存在于二維數組中時,返回,否則返回索引值。最后將緩存數量減少。 昨日我沿著河岸/漫步到/蘆葦彎腰喝水的地方順便請煙囪/在天空為我寫一封長長的信 潦是潦草了些/而我的心意/則明亮亦如你窗前的燭光/稍有曖昧之處/勢所難免/因為風的緣故 ——洛夫《因為風的緣故》 本文為讀 lodash 源碼的第七篇,后續文章會...

    SunZhaopeng 評論0 收藏0
  • 「讀懂源碼系列3」lodash 如何實現深拷貝(上)

    摘要:上對位運算的解釋是它經常被用來創建處理以及讀取標志位序列一種類似二進制的變量。位運算,常用于處理同時存在多個布爾選項的情形。掩碼中的每個選項的值都是的冪,位運算是位的。位運算,說白了就是直接對某個數據在內存中的二進制位,進行運算操作。 showImg(https://segmentfault.com/img/bVbrC56?w=2208&h=1242); 前言 上一篇文章 「前端面試題...

    flyer_dev 評論0 收藏0
  • 「讀懂源碼系列4」lodash 如何實現深拷貝(下)

    摘要:用于檢測自己是否在自己的原型鏈上如果是函數,則取出該函數的原型對象否則,取出對象的原型對象其中,的判斷,是為了確定的類型是對象或數組。相當于,而的構造函數是一個函數對象。 showImg(https://segmentfault.com/img/bVbq2N1?w=640&h=437); 前言 接著上一篇文章 lodash 是如何實現深拷貝的(上),今天會繼續解讀 _.cloneDee...

    zombieda 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<