摘要:如果項(xiàng)目中需要頻繁的進(jìn)行數(shù)據(jù)類型的判斷與獲取可以考慮進(jìn)行封裝,簡單的處理與已足夠。
前言
在js中數(shù)據(jù)我們經(jīng)常需要判斷或者獲取數(shù)據(jù)類型,大部分時候我們都是通過type加instanceof來組合判斷數(shù)據(jù)類型來實(shí)現(xiàn),大部分代碼中對于數(shù)據(jù)類型的獲取處理都比較丑陋,前段時間看了一下Q的源代碼中對數(shù)據(jù)類型的判斷與獲取處理,看起來相當(dāng)簡潔也比較好用,這篇文章來進(jìn)行一下發(fā)散。
typeof在js中我們判斷數(shù)據(jù)類型經(jīng)常會用到typeof,比如判斷一個數(shù)據(jù)是否是一個數(shù)字類型
var n = 99; typeof(n) === "number"; // true
這么做有一個缺點(diǎn),typeof只能判斷js中的基礎(chǔ)數(shù)據(jù)類型undefined、String、Number、Boolean、Object。如果需要判斷一個數(shù)據(jù)是不是Array類型,這個時候instanceof就派上用場了。
instanceof官方對于instanceof說明: 運(yùn)算符用來測試一個對象在其原型鏈中是否存在一個構(gòu)造函數(shù)的 prototype 屬性(翻譯成人話:判斷對象指向構(gòu)造函數(shù)名稱是否與構(gòu)造函數(shù)名一致),如圖:
判斷一個數(shù)據(jù)是否是時間類型,一般我們都這樣寫:
var list = []; list instanceof Date; // false
instanceof有一個缺點(diǎn),只能針對對象類型的數(shù)據(jù)進(jìn)行處理,因?yàn)橹挥袑ο笾胁虐玩減rototype,當(dāng)然平常我們用到的function數(shù)據(jù)類型也是對象的一種,還是一圖解千言,看一下js中的數(shù)據(jù)類型大概明了。
判斷null的數(shù)據(jù)類型在js中null也是Object中的一個子類型(關(guān)于null,可以看這篇文章),但是我們不能通過instanceof去獲取,因?yàn)閚ull中并沒有原型鏈prototype,于是我們有了這樣的代碼:
var str = "null"; str === null; // false基礎(chǔ)版本獲取數(shù)據(jù)類型
當(dāng)我們并不知道數(shù)據(jù)類型,但是需要獲這個數(shù)據(jù)的類型時,大部分童鞋的代碼里面都是這樣寫的:
classString(obj) { if (obj && (obj.__proto__ || obj.prototype)) { if (obj instanceof Array) { return "array"; } if (obj instanceof Function) { return "function"; } // 所有obj的衍生數(shù)據(jù)都判斷一遍 ... } else if (obj === null) { return "null"; // 返回字符串 } else { return typeof(obj); } }
這樣的代碼很繁雜,這么多的”if else“(俗稱面條代碼),既不美觀,也不實(shí)用。
升級版本獲取數(shù)據(jù)類型function classString(obj) { return ({}).toString.call(obj); } classString(null); // [object Null] classString("string"); // [object String] classString(function(){}); // [object Function] classString(new Date()); // [object Function]
有兩個關(guān)鍵方法:一個是call,另一個是Object.prototype.toString方法進(jìn)行處理。
先看call方法簡短描述:
fun.call(this, arg1, arg2, ...)
call: 調(diào)用一個函數(shù), 其具有一個指定的this值和分別地提供的參數(shù)(參數(shù)的列表)
再看一下關(guān)于call參數(shù)說明:
在fun函數(shù)運(yùn)行時指定的this值。需要注意的是,指定的this值并不一定是該函數(shù)執(zhí)行時真正的this值,如果這個函數(shù)處于非嚴(yán)格模式下,則指定為null和undefined的this值會自動指向全局對象,同時值為原始值(數(shù)字,字符串,布爾值)的this會指向該原始值的自動包裝對象。
只有當(dāng)this不存在上下文的時候,this才會指向全局對象(瀏覽器中就是window對象)。
”包裝對象“,并不是一種數(shù)據(jù)類型,原始數(shù)據(jù)類型中:字符串、數(shù)字、布爾值可以轉(zhuǎn)換成相應(yīng)的Number、String、Boolean對應(yīng)的原生對象(注意是對象,不是值),具體在call中的表現(xiàn)形式如下(左邊等價于右邊):
再舉個栗子?:
999 instanceof Number; // false new Number(999) instanceof Number; // true
關(guān)于Object toString方法的簡短說明:
默認(rèn)情況下,toString()方法被每個Object對象繼承。如果此方法在自定義對象中未被覆蓋,toString() 返回 "[object type]",其中type是對象的類型。
這里的type并不是js5中基礎(chǔ)數(shù)據(jù)類型相關(guān)的type,而是當(dāng)前對象中__proto__中指向的構(gòu)造函數(shù)名(關(guān)于__proto__。
自定義數(shù)據(jù)類型我們在開發(fā)的時候經(jīng)常需要自定義數(shù)據(jù),比如說我們自己創(chuàng)建了一個構(gòu)建函數(shù)F,當(dāng)我們獲取數(shù)據(jù)類型的時候期待返回的結(jié)果為”[object F]“,代碼如下
var F = function() {} var f1 = new F(); classString(f1); // [object Object]
期待的結(jié)果并未返回,原因是因?yàn)镺bject.prototype.toString方法只定義了自帶的對象類型返回,EcmaScript關(guān)于Object toString 規(guī)范:
我們可以直接重定義Object.prototype.toString:
Object.prototype.toString = function(){ // Do something ... }
這并不是一種很好的行為,一方面容易造成全局污染,另一方面也不利于進(jìn)行排錯;所以還是老老實(shí)實(shí)的在方法中判斷吧:
function classString(obj, customize) { if (customize && obj && obj.__proto__.constructor.name) { return "[object " + obj.__proto__.constructor.name + "]"; } return ({}).toString.call(obj); } var F = function() {} var f1 = new F(); classString(f1, true); // [object F] classString(f1); // [object Object]
為什么可以通過__proto__.constructor.name來獲取構(gòu)造函數(shù)名,object與function并不會造成混亂,object與function中的 proto 指向并不是相同的,這里不細(xì)講,還是參考關(guān)于__proto__。
優(yōu)化返回格式對于”[object type]“數(shù)據(jù)返回我們只需要獲取type即可,可以通過正則表達(dá)獲取type指,這里不做代碼說明。
其他1、關(guān)于call、toString方法平常都是信手拈來使用,沒有深入探究過,探究起來和以前自己腦海中的理解還是有些不同的。
2、 如果項(xiàng)目中需要頻繁的進(jìn)行數(shù)據(jù)類型的判斷與獲取可以考慮進(jìn)行封裝,簡單的處理typeof與instanceof已足夠。
3、上述代碼中只是簡單的示例,部分地方并不是十分嚴(yán)謹(jǐn)。
EcmaScript
MDN instanceof
MDN call
MDN types Array
undefined與null有什么區(qū)別
關(guān)于__proto__與prototype
EcmaScript Object toString
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/90689.html
摘要:項(xiàng)目下的緩存控制客戶端向服務(wù)端請求頁面的過程中,服務(wù)端是可控的??煽氐牟趴蓛?yōu)化,優(yōu)化的重點(diǎn),即是緩存優(yōu)化。如此就能提高數(shù)據(jù)響應(yīng)的速度,也保護(hù)了數(shù)據(jù)源。雖開啟擴(kuò)展可管理內(nèi)存,但所能管理的內(nèi)存大小是有限的。見下圖的英文注釋注意事項(xiàng) php項(xiàng)目下的緩存控制 客戶端向服務(wù)端請求php頁面的過程中,服務(wù)端是可控的。 可控的才可優(yōu)化,優(yōu)化的重點(diǎn),即是緩存優(yōu)化。 試想?數(shù)據(jù)存儲在DB中,訪問DB就...
摘要:項(xiàng)目下的緩存控制客戶端向服務(wù)端請求頁面的過程中,服務(wù)端是可控的??煽氐牟趴蓛?yōu)化,優(yōu)化的重點(diǎn),即是緩存優(yōu)化。如此就能提高數(shù)據(jù)響應(yīng)的速度,也保護(hù)了數(shù)據(jù)源。雖開啟擴(kuò)展可管理內(nèi)存,但所能管理的內(nèi)存大小是有限的。見下圖的英文注釋注意事項(xiàng) php項(xiàng)目下的緩存控制 客戶端向服務(wù)端請求php頁面的過程中,服務(wù)端是可控的。 可控的才可優(yōu)化,優(yōu)化的重點(diǎn),即是緩存優(yōu)化。 試想?數(shù)據(jù)存儲在DB中,訪問DB就...
摘要:原文譯文的消息通知機(jī)制譯者已經(jīng)被應(yīng)用到開發(fā)中。所以先要征求用戶的許可而不是直接顯示通知。然后,獲取用戶許可之后,我們可以顯示兩種類型的信息最后執(zhí)行通知代碼。 原文:HTML 5 Notification 譯文:HTML 5 的消息通知機(jī)制 譯者:dwqs showImg(https://segmentfault.com/img/bVks7a); HTML 5 已經(jīng)被應(yīng)用到Web...
摘要:多維數(shù)組本質(zhì)上和一維數(shù)組沒區(qū)別,他的維數(shù)僅僅只是作為比例因子和偏移,拿來計(jì)算地址偏移用的,但是多級指針用數(shù)組訪問的時候,他的維數(shù)僅僅只做偏移用,他的過程是加偏移,解引用,加偏移,解引用。。。。 類型 c語言中規(guī)定類型這樣一個事情,主要是出于一個怎樣的原因呢? char sho...
閱讀 1788·2021-11-16 11:44
閱讀 2484·2021-10-11 11:07
閱讀 4280·2021-10-09 09:41
閱讀 740·2021-09-22 15:52
閱讀 3279·2021-09-09 09:33
閱讀 2824·2019-08-30 15:55
閱讀 2338·2019-08-30 15:55
閱讀 896·2019-08-30 15:55