摘要:專題系列第四篇,講解類型判斷的各種方法,并且跟著寫一個函數(shù)。返回值為表示操作數(shù)類型的一個字符串。考慮到實際情況下并不會檢測和,所以去掉這兩個類型的檢測。
前言JavaScript專題系列第四篇,講解類型判斷的各種方法,并且跟著 jQuery 寫一個 type 函數(shù)。
類型判斷在 web 開發(fā)中有非常廣泛的應(yīng)用,簡單的有判斷數(shù)字還是字符串,進階一點的有判斷數(shù)組還是對象,再進階一點的有判斷日期、正則、錯誤類型,再再進階一點還有比如判斷 plainObject、空對象、Window 對象等等。
以上都會講,今天是上半場。
typeof我們最最常用的莫過于 typeof,注意,盡管我們會看到諸如:
console.log(typeof("yayu")) // string
的寫法,但是 typeof 可是一個正宗的運算符,就跟加減乘除一樣!這就能解釋為什么下面這種寫法也是可行的:
console.log(typeof "yayu") // string
引用《JavaScript權(quán)威指南》中對 typeof 的介紹:
typeof 是一元操作符,放在其單個操作數(shù)的前面,操作數(shù)可以是任意類型。返回值為表示操作數(shù)類型的一個字符串。
那我們都知道,在 ES6 前,JavaScript 共六種數(shù)據(jù)類型,分別是:
Undefined、Null、Boolean、Number、String、Object
然而當(dāng)我們使用 typeof 對這些數(shù)據(jù)類型的值進行操作的時候,返回的結(jié)果卻不是一一對應(yīng),分別是:
undefined、object、boolean、number、string、object
注意以上都是小寫的字符串。Null 和 Object 類型都返回了 object 字符串。
盡管不能一一對應(yīng),但是 typeof 卻能檢測出函數(shù)類型:
function a() {} console.log(typeof a); // function
所以 typeof 能檢測出六種類型的值,但是,除此之外 Object 下還有很多細(xì)分的類型吶,如 Array、Function、Date、RegExp、Error 等。
如果用 typeof 去檢測這些類型,舉個例子:
var date = new Date(); var error = new Error(); console.log(typeof date); // object console.log(typeof error); // object
返回的都是 object 吶,這可怎么區(qū)分~ 所以有沒有更好的方法呢?
Obejct.prototype.toString是的,當(dāng)然有!這就是 Object.prototype.toString!
那 Object.protototype.toString 究竟是一個什么樣的方法呢?
為了更加細(xì)致的講解這個函數(shù),讓我先獻(xiàn)上 ES5 規(guī)范地址:https://es5.github.io/#x15.2.4.2。
在第 15.2.4.2 節(jié)講的就是 Object.prototype.toString(),為了不誤導(dǎo)大家,我先奉上英文版:
When the toString method is called, the following steps are taken:
If the this value is undefined, return "[object Undefined]".
If the this value is null, return "[object Null]".
Let O be the result of calling ToObject passing the this value as the argument.
Let class be the value of the [[Class]] internal property of O.
Return the String value that is the result of concatenating the three Strings "[object ", class, and "]".
凡是規(guī)范上加粗或者斜體的,在這里我也加粗或者斜體了,就是要讓大家感受原汁原味的規(guī)范!
如果沒有看懂,就不妨看看我理解的:
當(dāng) toString 方法被調(diào)用的時候,下面的步驟會被執(zhí)行:
如果 this 值是 undefined,就返回 [object Undefined]
如果 this 的值是 null,就返回 [object Null]
讓 O 成為 ToObject(this) 的結(jié)果
讓 class 成為 O 的內(nèi)部屬性 [[Class]] 的值
最后返回由 "[object " 和 class 和 "]" 三個部分組成的字符串
通過規(guī)范,我們至少知道了調(diào)用 Object.prototype.toString 會返回一個由 "[object " 和 class 和 "]" 組成的字符串,而 class 是要判斷的對象的內(nèi)部屬性。
讓我們寫個 demo:
console.log(Object.prototype.toString.call(undefined)) // [object Undefined] console.log(Object.prototype.toString.call(null)) // [object Null] var date = new Date(); console.log(Object.prototype.toString.call(date)) // [object Date]
由此我們可以看到這個 class 值就是識別對象類型的關(guān)鍵!
正是因為這種特性,我們可以用 Object.prototype.toString 方法識別出更多類型!
那到底能識別多少種類型呢?
至少 12 種!
你咋知道的?
我數(shù)的!
……
讓我們看個 demo:
// 以下是11種: var number = 1; // [object Number] var string = "123"; // [object String] var boolean = true; // [object Boolean] var und = undefined; // [object Undefined] var nul = null; // [object Null] var obj = {a: 1} // [object Object] var array = [1, 2, 3]; // [object Array] var date = new Date(); // [object Date] var error = new Error(); // [object Error] var reg = /a/g; // [object RegExp] var func = function a(){}; // [object Function] function checkType() { for (var i = 0; i < arguments.length; i++) { console.log(Object.prototype.toString.call(arguments[i])) } } checkType(number, string, boolean, und, nul, obj, array, date, error, reg, func)
除了以上 11 種之外,還有:
console.log(Object.prototype.toString.call(Math)); // [object Math] console.log(Object.prototype.toString.call(JSON)); // [object JSON]
除了以上 13 種之外,還有:
function a() { console.log(Object.prototype.toString.call(arguments)); // [object Arguments] } a();
所以我們可以識別至少 14 種類型,當(dāng)然我們也可以算出來,[[class]] 屬性至少有 12 個。
type API既然有了 Object.prototype.toString 這個神器!那就讓我們寫個 type 函數(shù)幫助我們以后識別各種類型的值吧!
我的設(shè)想:
寫一個 type 函數(shù)能檢測各種類型的值,如果是基本類型,就使用 typeof,引用類型就使用 toString。此外鑒于 typeof 的結(jié)果是小寫,我也希望所有的結(jié)果都是小寫。
考慮到實際情況下并不會檢測 Math 和 JSON,所以去掉這兩個類型的檢測。
我們來寫一版代碼:
// 第一版 var class2type = {}; // 生成class2type映射 "Boolean Number String Function Array Date RegExp Object Error Null Undefined".split(" ").map(function(item, index) { class2type["[object " + item + "]"] = item.toLowerCase(); }) function type(obj) { return typeof obj === "object" || typeof obj === "function" ? class2type[Object.prototype.toString.call(obj)] || "object" : typeof obj; }
嗯,看起來很完美的樣子~~ 但是注意,在 IE6 中,null 和 undefined 會被 Object.prototype.toString 識別成 [object Object]!
我去,竟然還有這個兼容性!有什么簡單的方法可以解決嗎?那我們再改寫一版,絕對讓你驚艷!
// 第二版 var class2type = {}; // 生成class2type映射 "Boolean Number String Function Array Date RegExp Object Error".split(" ").map(function(item, index) { class2type["[object " + item + "]"] = item.toLowerCase(); }) function type(obj) { // 一箭雙雕 if (obj == null) { return obj + ""; } return typeof obj === "object" || typeof obj === "function" ? class2type[Object.prototype.toString.call(obj)] || "object" : typeof obj; }isFunction
有了 type 函數(shù)后,我們可以對常用的判斷直接封裝,比如 isFunction:
function isFunction(obj) { return type(obj) === "function"; }數(shù)組
jQuery 判斷數(shù)組類型,舊版本是通過判斷 Array.isArray 方法是否存在,如果存在就使用該方法,不存在就使用 type 函數(shù)。
var isArray = Array.isArray || function( obj ) { return type(obj) === "array"; }
但是在 jQuery v3.0 中已經(jīng)完全采用了 Array.isArray。
結(jié)語到此,類型判斷的上篇就結(jié)束了,我們已經(jīng)可以判斷日期、正則、錯誤類型啦,但是還有更復(fù)雜的判斷比如 plainObject、空對象、Window對象、類數(shù)組對象等,路漫漫其修遠(yuǎn)兮,吾將上下而求索。
哦, 對了,這個 type 函數(shù)抄的 jQuery,點擊查看 type 源碼。
專題系列JavaScript專題系列目錄地址:https://github.com/mqyqingfeng/Blog。
JavaScript專題系列預(yù)計寫二十篇左右,主要研究日常開發(fā)中一些功能點的實現(xiàn),比如防抖、節(jié)流、去重、類型判斷、拷貝、最值、扁平、柯里、遞歸、亂序、排序等,特點是研(chao)究(xi) underscore 和 jQuery 的實現(xiàn)方式。
如果有錯誤或者不嚴(yán)謹(jǐn)?shù)牡胤剑垊?wù)必給予指正,十分感謝。如果喜歡或者有所啟發(fā),歡迎 star,對作者也是一種鼓勵。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/83681.html
摘要:專題系列共計篇,主要研究日常開發(fā)中一些功能點的實現(xiàn),比如防抖節(jié)流去重類型判斷拷貝最值扁平柯里遞歸亂序排序等,特點是研究專題之函數(shù)組合專題系列第十六篇,講解函數(shù)組合,并且使用柯里化和函數(shù)組合實現(xiàn)模式需求我們需要寫一個函數(shù),輸入,返回。 JavaScript 專題之從零實現(xiàn) jQuery 的 extend JavaScritp 專題系列第七篇,講解如何從零實現(xiàn)一個 jQuery 的 ext...
摘要:寫在前面專題系列是我寫的第二個系列,第一個系列是深入系列。專題系列自月日發(fā)布第一篇文章,到月日發(fā)布最后一篇,感謝各位朋友的收藏點贊,鼓勵指正。 寫在前面 JavaScript 專題系列是我寫的第二個系列,第一個系列是 JavaScript 深入系列。 JavaScript 專題系列共計 20 篇,主要研究日常開發(fā)中一些功能點的實現(xiàn),比如防抖、節(jié)流、去重、類型判斷、拷貝、最值、扁平、柯里...
摘要:不過的實現(xiàn)中,多了很多細(xì)節(jié)上的判斷,比如第一個參數(shù)是否是布爾值,是否是一個對象,不傳參數(shù)時的默認(rèn)值等。 JavaScritp 專題系列第七篇,講解如何從零實現(xiàn)一個 jQuery 的 extend 函數(shù) 前言 jQuery 的 extend 是 jQuery 中應(yīng)用非常多的一個函數(shù),今天我們一邊看 jQuery 的 extend 的特性,一邊實現(xiàn)一個 extend! extend 基本用...
摘要:將元素作為對象的鍵,默認(rèn)鍵對應(yīng)的值為如果對象中沒有這個鍵,則將這個元素放入結(jié)果數(shù)組中去。 前言 數(shù)組去重在日常開發(fā)中的使用頻率還是較高的,也是網(wǎng)上隨便一抓一大把的話題,所以,我寫這篇文章目的在于歸納和總結(jié),既然很多人都在提的數(shù)組去重,自己到底了解多少呢。又或者是如果自己在開發(fā)中遇到了去重的需求,自己能想到更好的解決方案嗎。 這次我們來理一理怎么做數(shù)組去重才能做得最合適,既要考慮兼容性,...
摘要:專題系列預(yù)計寫二十篇左右,主要研究日常開發(fā)中一些功能點的實現(xiàn),比如防抖節(jié)流去重類型判斷拷貝最值扁平柯里遞歸亂序排序等,特點是研究和的實現(xiàn)方式。 JavaScript專題系列第五篇,講解更加復(fù)雜的類型判斷,比如 plainObject、空對象、類數(shù)組對象、Window對象、DOM 元素等 前言 在上篇《JavaScript專題之類型判斷(上)》中,我們抄襲 jQuery 寫了一個 typ...
閱讀 1330·2021-11-15 18:14
閱讀 3303·2021-08-25 09:38
閱讀 2735·2019-08-30 10:55
閱讀 2792·2019-08-29 16:39
閱讀 1370·2019-08-29 15:07
閱讀 2504·2019-08-29 14:14
閱讀 876·2019-08-29 12:36
閱讀 972·2019-08-29 11:21