摘要:與之前的類似,利用構(gòu)造函數(shù)創(chuàng)建的字符串是一個(gè)所以檢測(cè)字符串,除了基本字符串以外還要注意字符串對(duì)象。也就是說(shuō)該對(duì)象由構(gòu)造函數(shù)創(chuàng)建,或者為。
原文:https://fatge.github.io/2019/...
歡迎Star:https://github.com/FatGe/FatG...
JS 的基本數(shù)據(jù)類型有 Number,String,Boolean,Symbol,Null,Undefined,六種數(shù)據(jù)類型。一種引用類型 object。
基本數(shù)據(jù)類型 Number數(shù)值,根據(jù) ECMAScript 標(biāo)準(zhǔn),JavaScript 中只有一種數(shù)字類型:基于 IEEE 754 標(biāo)準(zhǔn)的雙精度 64 位二進(jìn)制格式的值(-(263 -1) 到 263 -1)。它并沒(méi)有為整數(shù)給出一種特定的類型。
除了能夠表示浮點(diǎn)數(shù)外,還有一些帶符號(hào)的值:+Infinity,-Infinity 和 NaN (非數(shù)值,Not-a-Number)。
對(duì)應(yīng) lodash 中的檢測(cè)函數(shù)有
isNumber 檢查 value 是否是原始 Number 數(shù)值型 或者 對(duì)象;
isInteger 檢查 value 是否為一個(gè)整數(shù);
isNaN 檢測(cè) value 是否為 NaN;
isFinite 檢測(cè) value 是否是原始有限數(shù)值。
function isNumber(value) { return typeof value == "number" || (isObjectLike(value) && getTag(value) == "[object Number]") }
typeof 操作符可以返回一個(gè)字符串,表示未經(jīng)計(jì)算的操作數(shù)的類型。對(duì)于 Number、String、Boolean、Undefined、String 可以很明確的得到它的類型。
那么 lodash 為什么還要添加 (isObjectLike(value) && getTag(value) == "[object Number]")?
原因在于,JS 中也允許我們以如下形式創(chuàng)建一個(gè)數(shù)值
const value = new Number(1) console.log(value) // log 1 console.log(typeof value) // log "object"
這時(shí),單單只是使用 typeof 操作符就沒(méi)法判斷 value 的類型是否為數(shù)值。所以要結(jié)合以下兩個(gè)函數(shù)來(lái)判斷,value 是否為 object 然后再通過(guò)過(guò) toString() 來(lái)獲取每個(gè)對(duì)象的類型。
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 每個(gè)對(duì)象都有一個(gè)toString()方法,當(dāng)該對(duì)象被表示為一個(gè)文本值時(shí),或者一個(gè)對(duì)象以預(yù)期的字符串方式引用時(shí)自動(dòng)調(diào)用。
function isInteger(value) { return typeof value == "number" && value == toInteger(value); }
檢查 value 是否為一個(gè)整數(shù),判斷是否 value 的類型是否為數(shù)值,并且是否與 Int 型相同。其取整過(guò)程如下
function toInteger(value) { var result = toFinite(value), remainder = result % 1; return result === result ? (remainder ? result - remainder : result) : 0; }
檢查 value 是否是 NaN。
function isNaN(value) { return isNumber(value) && value != +value; }
與 ES 2015 的 isNaN 不同的是,對(duì)于 undefined,{},原生的結(jié)果是 true,而 lodash 為 false。這是因?yàn)槿绻?b>isNaN函數(shù)的參數(shù)不是Number類型, isNaN函數(shù)會(huì)首先嘗試將這個(gè)參數(shù)轉(zhuǎn)換為數(shù)值,然后才會(huì)對(duì)轉(zhuǎn)換后的結(jié)果是否是NaN進(jìn)行判斷。
// js native isNaN var isNaN = function(value) { var n = Number(value); return n !== n; };
但是無(wú)論是 ES 2015 還是 lodash,它們本質(zhì)上都是利用 x != x 來(lái)判斷 NaN。
檢查 value 是否是原始有限數(shù)值。
function isFinite(value) { return typeof value == "number" && nativeIsFinite(value); }
利用原生的 isFinite 結(jié)合 typeof 判斷數(shù)字是否為有限值。
StringString 類型用于表示由零或多個(gè)16 位Unicode 字符組成的字符序列,即字符串。用于保存可以以文本形式表示的數(shù)據(jù)非常有用。
值得注意的是,不單單要注意基本字符串,還需要注意字符串對(duì)象,字符串字面量 (通過(guò)單引號(hào)或雙引號(hào)定義) 和 直接調(diào)用 String 方法(沒(méi)有通過(guò) new 生成字符串對(duì)象實(shí)例)的字符串都是基本字符串。
JavaScript會(huì)自動(dòng)將基本字符串轉(zhuǎn)換為字符串對(duì)象,只有將基本字符串轉(zhuǎn)化為字符串對(duì)象之后才可以使用字符串對(duì)象的方法。
與之前的 number 類似,利用構(gòu)造函數(shù) String 創(chuàng)建的字符串是一個(gè) 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"
所以檢測(cè)字符串,除了基本字符串以外還要注意字符串對(duì)象。
function isString(value) { const type = typeof value return type == "string" || (type == "object" && value != null && !Array.isArray(value) && getTag(value) == "[object String]") }
可以利用 typeof 檢測(cè)基本字符串,對(duì)于模板字符串采用了之前介紹的方案 getTag 來(lái)獲取 value 的類型。
BooleanBoolean 類型是ECMAScript 中使用得最多的一種類型,該類型只有兩個(gè)字面值:true 和 false。同樣也需要區(qū)分基本的 Boolean 類型以及 Boolean 對(duì)象。
function isBoolean(value) { return value === true || value === false || (isObjectLike(value) && getTag(value) == "[object Boolean]") }
大部分在之前都已經(jīng)涉及到了,這里出現(xiàn)了 isObjectLike,那么它是做什么的。
function isObjectLike(value) { return typeof value == "object" && value !== null }
原來(lái)只是檢測(cè)是否是一個(gè)非 null 的對(duì)象。
SymbolES6 引入了一種新的原始數(shù)據(jù)類型Symbol,表示獨(dú)一無(wú)二的值。Symbol 值通過(guò)Symbol函數(shù)生成。
function isSymbol(value) { const type = typeof value return type == "symbol" || (isObjectLike(value) && getTag(value) == "[object Symbol]") }
會(huì)發(fā)現(xiàn) (isObjectLike(value) && getTag(value) == "[object Symbol]"),也對(duì) Symbol 對(duì)象進(jìn)行檢測(cè),但是如果直接 new Symbol 會(huì) log 出 TypeError。
那么 lodash 為什么要對(duì)其進(jìn)行檢測(cè),原來(lái)是創(chuàng)建一個(gè)顯式包裝器對(duì)象從 ECMAScript 6 開始不再被支持,現(xiàn)在可以利用如下代碼來(lái)模擬,雖然沒(méi)什么用。
const sym = Symbol("foo"); typeof sym; // "symbol" const symObj = Object(sym); typeof symObj; // "object"Undefined
Undefined 類型只有一個(gè)值,即特殊的 undefined。在使用 let 或 var 聲明變量但未對(duì)其加以初始化時(shí),這個(gè)變量的值就是 undefined。
function isUndefined(value) { return value === undefined; }Null
Null 類型是只有一個(gè)值的數(shù)據(jù)類型,這個(gè)特殊的值是 null 。與 undefined 不同的是,它是一個(gè)字面量,而 undefined 是全局對(duì)象的一個(gè)屬性。
從邏輯角度來(lái)看,null 值表示一個(gè)空對(duì)象指針,null 是表示缺少的標(biāo)識(shí),指示變量未指向任何對(duì)象。而這也正是使用typeof 操作符檢測(cè)null 值時(shí)會(huì)返回"object"的原因。
對(duì)其的判斷也非常的簡(jiǎn)單,只需要
function isNull(value) { return value === null }
當(dāng)然你也可以使用
console.log(Object.prototype.toString.call(null)) // [object Null]
以上是基本數(shù)據(jù)類型的判斷,總結(jié)一下,主要是利用 typeOf 以及 Object.prototype.toString ,還有一些特殊值的特性。下面開始分析引用類型 Object
引用類型引用類型的值(對(duì)象)是引用類型的一個(gè)實(shí)例。在ECMAScript 中,引用類型是一種數(shù)據(jù)結(jié)構(gòu),用于將數(shù)據(jù)和功能組織在一起。具體的有 Object 、Array、Date、Error、RegExp、Function,還有ES2015 引入 Set、Map、WeakSet、WeakMap。
ObjectECMAScript 中的對(duì)象其實(shí)就是一組數(shù)據(jù)和功能的集合。它有一個(gè)很重要的用途,就是在 JavaScript 中的所有對(duì)象都來(lái)自 Object;所有對(duì)象從Object.prototype繼承方法和屬性,盡管它們可能被覆蓋。即在ECMAScript 中,Object 類型是所有它的實(shí)例的基礎(chǔ)。
所以 Lodash 去判斷 value 是否為 Object 時(shí),只使用了 typeOf 操作即可。
function isObject(value) { const type = typeof value return value != null && (type == "object" || type == "function") }Function
Function 構(gòu)造函數(shù) 創(chuàng)建一個(gè)新的Function對(duì)象。 在 JavaScript 中, 每個(gè)函數(shù)實(shí)際上都是一個(gè)Function對(duì)象。
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]" }
有個(gè)問(wèn)題,typeOf 可以檢測(cè) Function對(duì)象的類型為 Function, 那為什么還需要 Object.prototype.toString 呢?
// in Safari 9 which returns "object" for typed arrays and other constructors.Array
Array 在 ECMAScript 中代表數(shù)組,它的每一項(xiàng)可以保存任何類型的數(shù)據(jù)。
對(duì)它的常規(guī)檢測(cè)就是 Array.isArray,Lodash 也是使用這個(gè) API,如果需要 Polyfill 方案的話,可以使用
// plan 1 Object.prototype.toString.call(value) === "[object Array]" // plan 2 value.constructor === Array
之前還有 value instanceof Array 會(huì)什么問(wèn)題么?
在存在不同全局變量的環(huán)境,通過(guò)語(yǔ)義 instanceof 檢測(cè)數(shù)組的時(shí)候,value instanceof Array只有當(dāng) value 是由該頁(yè)面的原始 Array 構(gòu)造函數(shù)創(chuàng)建的數(shù)組時(shí)才能正常工作。Date具體請(qǐng)見,http://web.mit.edu/jwalden/ww...。
ECMAScript 中的 Date 類型是在早期Java 中的java.util.Date 類基礎(chǔ)上構(gòu)建的。
const nodeIsDate = nodeTypes && nodeTypes.isDate const isDate = nodeIsDate ? (value) => nodeIsDate(value) : (value) => isObjectLike(value) && getTag(value) == "[object Date]"
Lodash 分為兩個(gè)環(huán)境來(lái)處理這個(gè)問(wèn)題,如果是 Node 就利用 util.types.isDate(value) 來(lái)檢測(cè),如果是在游覽器,就還是通過(guò) Object.prototype.toString 來(lái)判斷。
SetES2015 提供了新的數(shù)據(jù)結(jié)構(gòu) Set。它類似于數(shù)組,但是成員的值都是唯一的,沒(méi)有重復(fù)的值。
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 結(jié)構(gòu)與 Set 類似,也是不重復(fù)的值的集合。但是,它與 Set 有兩個(gè)區(qū)別。
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
當(dāng)運(yùn)行時(shí)錯(cuò)誤產(chǎn)生時(shí),Error的實(shí)例對(duì)象會(huì)被拋出。
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 依然可以用來(lái)判斷對(duì)象是否是一個(gè) Error,除此之外,如果對(duì)象滿足以下條件,也可以被視為一個(gè) Error
具備 message、name 屬性,且值為 string;
是普通對(duì)象。 也就是說(shuō)該對(duì)象由 Object 構(gòu)造函數(shù)創(chuàng)建,或者 [[Prototype]] 為 null 。
那么如何檢測(cè)普通對(duì)象呢?
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() 方法返回指定對(duì)象的原型(內(nèi)部[[Prototype]]屬性的值),同時(shí)和 value 本身的 [[Prototype]] 做判斷。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/106178.html
摘要:深拷貝是一件看起來(lái)很簡(jiǎn)單的事情,但其實(shí)一點(diǎn)兒也不簡(jiǎn)單。我們也可以利用這個(gè)實(shí)現(xiàn)對(duì)象的深拷貝。而是利用之前已經(jīng)拷貝好的值。深拷貝的詳細(xì)的源碼可以在這里查看。大功告成我們雖然的確解決了深拷貝的大部分問(wèn)題。 js深拷貝是一件看起來(lái)很簡(jiǎn)單的事情,但其實(shí)一點(diǎn)兒也不簡(jiǎn)單。對(duì)于循環(huán)引用的問(wèn)題還有一些內(nèi)置數(shù)據(jù)類型的拷貝,如Map, Set, RegExp, Date, ArrayBuffer 和其他內(nèi)置...
摘要:在之前的文章中已經(jīng)介紹過(guò),檢測(cè)的是對(duì)應(yīng)的數(shù)組在二維數(shù)組中的索引,其行為跟一致,不存在于二維數(shù)組中時(shí),返回,否則返回索引值。最后將緩存數(shù)量減少。 昨日我沿著河岸/漫步到/蘆葦彎腰喝水的地方順便請(qǐng)煙囪/在天空為我寫一封長(zhǎng)長(zhǎng)的信 潦是潦草了些/而我的心意/則明亮亦如你窗前的燭光/稍有曖昧之處/勢(shì)所難免/因?yàn)轱L(fēng)的緣故 ——洛夫《因?yàn)轱L(fēng)的緣故》 本文為讀 lodash 源碼的第七篇,后續(xù)文章會(huì)...
摘要:在之前的文章中已經(jīng)介紹過(guò),檢測(cè)的是對(duì)應(yīng)的數(shù)組在二維數(shù)組中的索引,其行為跟一致,不存在于二維數(shù)組中時(shí),返回,否則返回索引值。最后將緩存數(shù)量減少。 昨日我沿著河岸/漫步到/蘆葦彎腰喝水的地方順便請(qǐng)煙囪/在天空為我寫一封長(zhǎng)長(zhǎng)的信 潦是潦草了些/而我的心意/則明亮亦如你窗前的燭光/稍有曖昧之處/勢(shì)所難免/因?yàn)轱L(fēng)的緣故 ——洛夫《因?yàn)轱L(fēng)的緣故》 本文為讀 lodash 源碼的第七篇,后續(xù)文章會(huì)...
摘要:上對(duì)位運(yùn)算的解釋是它經(jīng)常被用來(lái)創(chuàng)建處理以及讀取標(biāo)志位序列一種類似二進(jìn)制的變量。位運(yùn)算,常用于處理同時(shí)存在多個(gè)布爾選項(xiàng)的情形。掩碼中的每個(gè)選項(xiàng)的值都是的冪,位運(yùn)算是位的。位運(yùn)算,說(shuō)白了就是直接對(duì)某個(gè)數(shù)據(jù)在內(nèi)存中的二進(jìn)制位,進(jìn)行運(yùn)算操作。 showImg(https://segmentfault.com/img/bVbrC56?w=2208&h=1242); 前言 上一篇文章 「前端面試題...
摘要:用于檢測(cè)自己是否在自己的原型鏈上如果是函數(shù),則取出該函數(shù)的原型對(duì)象否則,取出對(duì)象的原型對(duì)象其中,的判斷,是為了確定的類型是對(duì)象或數(shù)組。相當(dāng)于,而的構(gòu)造函數(shù)是一個(gè)函數(shù)對(duì)象。 showImg(https://segmentfault.com/img/bVbq2N1?w=640&h=437); 前言 接著上一篇文章 lodash 是如何實(shí)現(xiàn)深拷貝的(上),今天會(huì)繼續(xù)解讀 _.cloneDee...
閱讀 3233·2021-11-11 16:55
閱讀 2498·2021-10-13 09:39
閱讀 2427·2021-09-13 10:27
閱讀 2163·2019-08-30 15:55
閱讀 3093·2019-08-30 15:54
閱讀 3137·2019-08-29 16:34
閱讀 1829·2019-08-29 12:41
閱讀 1073·2019-08-29 11:33