javascript中對變量類型的推斷

本文正式地址:http://www.xiabingbao.com/javascript/2015/07/04/javascript-type

在JavaScript中,有5種基本數據類型和1種復雜數據類型,基本數據類型有:Undefined,?Null,?Boolean,?NumberString。復雜數據類型是ObjectObject中還細分了非常多詳細的類型,比方:Array,?Function,?Date等等。今天我們就來探討一下,使用什么方法推斷一個出一個變量的類型。

在解說各種方法之前。我們首先定義出幾個測試變量,看看后面的方法到底能把變量的類型解析成什么樣子,以下幾個變量差點兒相同包括了我們在實際編碼中經常使用的類型。

var num  = 123;
var str  = 'abcdef';
var bool = true;
var arr  = [1, 2, 3, 4];
var json = {name:'wenzi', age:25};
var func = function(){ console.log('this is function'); }
var und  = undefined;
var nul  = null;
var date = new Date();
var reg  = /^[a-zA-Z]{5,20}$/;
var error= new Error();

1. 使用typeof檢測

我們平時用的最多的就是用typeof檢測變量類型了。

這次,我們也使用typeof檢測變量的類型:

console.log(typeof num, typeof str, typeof bool, typeof arr, typeof json, typeof func, typeof und, typeof nul, typeof date, typeof reg, typeof error
);
// number string boolean object object function undefined object object object object

從輸出的結果來看,arr, json, nul, date, reg, error 全部被檢測為object類型。其它的變量能夠被正確檢測出來。當須要變量是否是number,?string,?boolean,?function,?undefined, json類型時。能夠使用typeof進行推斷。其它變量是推斷不出類型的,包括null。

還有。typeof是區分不出arrayjson類型的。由于使用typeof這個變量時,array和json類型輸出的都是object

2. 使用instance檢測

在 JavaScript 中,推斷一個變量的類型嘗嘗會用 typeof 運算符。在使用 typeof 運算符時採用引用類型存儲值會出現一個問題,不管引用的是什么類型的對象,它都返回 “object”。ECMAScript 引入了還有一個 Java 運算符 instanceof 來解決問題。instanceof 運算符與 typeof 運算符相似,用于識別正在處理的對象的類型。

與 typeof 方法不同的是,instanceof 方法要求開發人員明白地確認對象為某特定類型。

比如:

function Person(){}
var Tom = new Person();
console.log(Tom instanceof Person); // true

我們再看看以下的樣例:

function Person(){}
function Student(){}
Student.prototype = new Person();
var John = new Student();
console.log(John instanceof Student); // true
console.log(John instancdof Person);  // true

instanceof還能檢測出多層繼承的關系。

好了。我們來使用instanceof檢測上面的那些變量:

console.log(num instanceof Number,str instanceof String,bool instanceof Boolean,arr instanceof Array,json instanceof Object,func instanceof Function,und instanceof Object,nul instanceof Object,date instanceof Date,reg instanceof RegExp,error instanceof Error
)
// num : false 
// str : false 
// bool : false 
// arr : true 
// json : true 
// func : true 
// und : false 
// nul : false 
// date : true 
// reg : true 
// error : true

從上面的執行結果我們能夠看到,num, str和bool沒有檢測出他的類型,可是我們使用以下的方式創建num,是能夠檢測出類型的:

var num = new Number(123);
var str = new String('abcdef');
var boolean = new Boolean(true);

同一時候,我們也要看到,und和nul是檢測的Object類型,才輸出的true,由于js中沒有UndefinedNull的這樣的全局類型,他們und和nul都屬于Object類型,因此輸出了true。

3. 使用constructor檢測

在使用instanceof檢測變量類型時。我們是檢測不到number, ‘string’,?bool的類型的。

因此,我們須要換一種方式來解決問題。

constructor本來是原型對象上的屬性,指向構造函數。可是根據實例對象尋找屬性的順序,若實例對象上沒有實例屬性或方法時,就去原型鏈上尋找,因此,實例對象也是能使用constructor屬性的。

我們先來輸出一下num.constructor的內容,即數字類型的變量的構造函數是什么樣子的:

function Number() { [native code] }

我們能夠看到它指向了Number的構造函數。因此,我們能夠使用num.constructor==Number來推斷num是不是Number類型的。其它的變量也相似:

function Person(){}
var Tom = new Person();// undefined和null沒有constructor屬性
console.log(Tom.constructor==Person,num.constructor==Number,str.constructor==String,bool.constructor==Boolean,arr.constructor==Array,json.constructor==Object,func.constructor==Function,date.constructor==Date,reg.constructor==RegExp,error.constructor==Error
);
// 全部結果均為true

從輸出的結果我們能夠看出,除了undefined和null。其它類型的變量均能使用constructor推斷出類型。

不過使用constructor也不是保險的,由于constructor屬性是能夠被改動的,會導致檢測出的結果不對,比如:

function Person(){}
function Student(){}
Student.prototype = new Person();
var John = new Student();
console.log(John.constructor==Student); // false
console.log(John.constructor==Person);  // true

在上面的樣例中,Student原型中的constructor被改動為指向到Person,導致檢測不出實例對象John真實的構造函數。

同一時候,使用instaceof和construcor,被推斷的array必須是在當前頁面聲明的!比方。一個頁面(父頁面)有一個框架,框架中引用了一個頁面(子頁面),在子頁面中聲明了一個array,并將其賦值給父頁面的一個變量。這時推斷該變量。Array == object.constructor;會返回false;?
原因:?
1、array屬于引用型數據。在傳遞過程中。不過引用地址的傳遞。?
2、每一個頁面的Array原生對象所引用的地址是不一樣的,在子頁面聲明的array,所相應的構造函數。是子頁面的Array對象。父頁面來進行推斷,使用的Array并不等于子頁面的Array。切記。不然非常難跟蹤問題!

4. 使用Object.prototype.toString.call

我們先不管這個是什么,先來看看他是怎么檢測變量類型的:

console.log(Object.prototype.toString.call(num),Object.prototype.toString.call(str),Object.prototype.toString.call(bool),Object.prototype.toString.call(arr),Object.prototype.toString.call(json),Object.prototype.toString.call(func),Object.prototype.toString.call(und),Object.prototype.toString.call(nul),Object.prototype.toString.call(date),Object.prototype.toString.call(reg),Object.prototype.toString.call(error)
);
// '[object Number]' '[object String]' '[object Boolean]' '[object Array]' '[object Object]'
// '[object Function]' '[object Undefined]' '[object Null]' '[object Date]' '[object RegExp]' '[object Error]'

從輸出的結果來看,Object.prototype.toString.call(變量)輸出的是一個字符串,字符串里有一個數組,第一個參數是Object,第二個參數就是這個變量的類型,并且,全部變量的類型都檢測出來了,我們只須要取出第二個參數就可以。

或者能夠使用Object.prototype.toString.call(arr)=="object Array"來檢測變量arr是不是數組。

我們如今再來看看ECMA里是是怎么定義Object.prototype.toString.call的:

Object.prototype.toString( ) When the toString method is called, the following steps are taken:?
1. Get the [[Class]] property of this object.?
2. Compute a string value by concatenating the three strings “[object “, Result (1), and “]”.?
3. Return Result (2)

上面的規范定義了Object.prototype.toString的行為:首先,取得對象的一個內部屬性[[Class]],然后根據這個屬性,返回一個相似于”[object Array]”的字符串作為結果(看過ECMA標準的應該都知道,[[]]用來表示語言內部用到的、外部不可直接訪問的屬性。稱為“內部屬性”)。利用這種方法,再配合call,我們能夠取得不論什么對象的內部屬性[[Class]]。然后把類型檢測轉化為字符串比較,以達到我們的目的。

5. jquery中$.type的實現

在jquery中提供了一個$.type的接口,來讓我們檢測變量的類型:

console.log($.type(num),$.type(str),$.type(bool),$.type(arr),$.type(json),$.type(func),$.type(und),$.type(nul),$.type(date),$.type(reg),$.type(error)
);
// number string boolean array object function undefined null date regexp error

看到輸出結果,有沒有一種熟悉的感覺?對,他就是上面使用Object.prototype.toString.call(變量)輸出的結果的第二個參數呀。

我們這里先來對照一下上面全部方法檢測出的結果,橫排是使用的檢測方法, 豎排是各個變量:

類型推斷typeofinstanceofconstructortoString.call$.type
numnumberfalsetrue[object Number]number
strstringfalsetrue[object String]string
boolbooleanfalsetrue[object Boolean]boolean
arrobjecttruetrue[object Array]array
jsonobjecttruetrue[object Object]object
funcfunctiontruetrue[object Function]function
undundefinedfalse-[object Undefined]undefined
nulobjectfalse-[object Null]null
dateobjecttruetrue[object Date]date
regobjecttruetrue[object RegExp]regexp
errorobjecttruetrue[object Error]error
長處使用簡單,能直接輸出結果能檢測出復雜的類型基本能檢測出全部的類型檢測出全部的類型-
缺點檢測出的類型太少基本類型檢測不出,且不能跨iframe不能跨iframe,且constructor易被改動IE6下undefined,null均為Object-

這樣對照一下,就更能看到各個方法之間的差別了,并且Object.prototype.toString.call$type輸出的結果真的非常像。我們來看看jquery(2.1.2版本號)內部是怎么實現$.type方法的:

// 實例對象是能直接使用原型鏈上的方法的
var class2type = {};
var toString = class2type.toString;// 省略部分代碼...type: function( obj ) {if ( obj == null ) {return obj + "";}// Support: Android<4.0, iOS<6 (functionish RegExp)return (typeof obj === "object" || typeof obj === "function") ?(class2type[ toString.call(obj) ] || "object") :typeof obj;
},// 省略部分代碼... // Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {class2type[ "[object " + name + "]" ] = name.toLowerCase();
});

我們先來看看jQuery.each的這部分:

// Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {class2type[ "[object " + name + "]" ] = name.toLowerCase();
});//循環之后,`class2type`的值是: 
class2type = {'[object Boolean]' : 'boolean', '[object Number]'  : 'number','[object String]'  : 'string','[object Function]': 'function','[object Array]'   : 'array','[object Date]'    : 'date','[object RegExp]'  : 'regExp','[object Object]'  : 'object','[object Error]'   : 'error'
}

再來看看type方法:

// type的實現
type: function( obj ) {// 若傳入的是null或undefined。則直接返回這個對象的字符串// 即若傳入的對象obj是undefined。則返回"undefined"if ( obj == null ) {return obj + "";}// Support: Android<4.0, iOS<6 (functionish RegExp)// 低版本號regExp返回function類型;高版本號已修正,返回object類型// 若使用typeof檢測出的obj類型是object或function。則返回class2type的值,否則返回typeof檢測的類型return (typeof obj === "object" || typeof obj === "function") ?(class2type[ toString.call(obj) ] || "object") :typeof obj;
}

typeof obj === "object" || typeof obj === "function"時,就返回class2type[ toString.call(obj)

到這兒,我們就應該明白為什么Object.prototype.toString.call和$.type那么像了吧,事實上jquery中就是用Object.prototype.toString.call實現的。把’[object Boolean]’類型轉成’boolean’類型并返回。若class2type存儲的沒有這個變量的類型,那就返回”object”。?
除了”object”和”function”類型。其它的類型則使用typeof進行檢測。即number,?string,?boolean類型的變量,使用typeof就可以。

本文正式地址:http://www.xiabingbao.com/javascript/2015/07/04/javascript-type








本文轉自mfrbuaa博客園博客,原文鏈接:http://www.cnblogs.com/mfrbuaa/p/5202979.html,如需轉載請自行聯系原作者

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/393781.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/393781.shtml
英文地址,請注明出處:http://en.pswp.cn/news/393781.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

U盤流暢運行linux發行版,做各種linux發行版的啟動U盤方法

偶用tuxboot先移植gparted到16GB的U盤。然后裁剪N個iso 做成一個U盤安裝或體驗N個系統的多功能盤。選單曬出來&#xff1a;default vesamenu.c32timeout 3000prompt 0menu title Android RHEL6.4 Ubuntu13.04 GpartedMENU BACKGROUND Gsplash.pnglabel 001menu label GRUB4DOSk…

采樣次數不同平均值不一樣_不同的真石漆裝飾效果也是不一樣的

外墻真石漆真的是一件很好的產品&#xff0c;具有防火性、防水性、安全且環保、粘力強、永不褪色等特點&#xff0c;無疑是人們較好的選擇&#xff0c;在很早之前就已經逐漸的取代了瓷磚和其他石材在人們心中的位置。真石漆的品種不止一種&#xff0c;按照裝飾效果我們可以分為…

No-3.Linux 終端命令格式

Linux 終端命令格式 01. 終端命令格式 command [-options] [parameter]說明&#xff1a; command&#xff1a;命令名&#xff0c;相應功能的英文單詞或單詞的縮寫[-options]&#xff1a;選項&#xff0c;可用來對命令進行控制&#xff0c;也可以省略parameter&#xff1a;傳給命…

電子設計速成_Web設計速成課程:從一個非設計者到另一個

電子設計速成by Ali Spittel通過Ali Spittel Web設計速成課程&#xff1a;從一個非設計者到另一個 (A Web Design Crash Course: from one non-designer to another) I will preface this by saying that I’m not a professional designer. That being said, I like building…

android項目方法數超過65536的解決辦法

2019獨角獸企業重金招聘Python工程師標準>>> 當項目的總方法數超過65536個&#xff0c;運行在手機上&#xff0c;指不定會報找不到哪個文件的錯。 我把項目的PullRefresh框架切換為SmartRefresh框架出現了方法數超過65536。 此文只是做一下筆記&#xff0c;不多做解…

leetcode1046. 最后一塊石頭的重量(堆)

有一堆石頭&#xff0c;每塊石頭的重量都是正整數。 每一回合&#xff0c;從中選出兩塊 最重的 石頭&#xff0c;然后將它們一起粉碎。假設石頭的重量分別為 x 和 y&#xff0c;且 x < y。那么粉碎的可能結果如下&#xff1a; 如果 x y&#xff0c;那么兩塊石頭都會被完全…

[Linux]幾個armhf的ubuntu源

摘自百度貼吧&#xff0c;留存 http://mirrors.ustc.edu.cn/ubuntu-ports/http://ftp.ubuntu-tw.org/mirror/ubuntu-ports/http://mirror.csclub.uwaterloo.ca/ubuntu-ports/http://mirrors.mit.edu/ubuntu-ports/ 速度從上到下越來越慢 中科技大 > 臺灣新北 > 滑鐵盧大學…

asp.net Linux 界面,在 ASP.NET 中實現不同角色的用戶使用不同登錄界面的方法

很多用戶在開發 ASP.NET應用程序時都有這樣的需求&#xff1a;管理員角色的賬戶使用管理員的登錄界面進行登錄&#xff0c;普通用戶角色的賬戶使用普通用戶的登錄界面進行登錄。由于ASP.NET的web.config里只能使用一個 authentication mode"Forms"節點&#xff0c;所…

pandas之Series

知識點 Pandas的數據類型有兩種&#xff1a;1、Series 一維&#xff0c;帶標簽數組2、DataFrame 二維&#xff0c;Series容器Serial對象本質上由兩個數組構成&#xff0c;一個數組構成對象的健(index,索引),一個數組構成對象的值(values).因此Series可以看作是鍵值對(健-->值…

python快樂數字怎么表達_Python經典面試題:這些面試題你會了嗎?

前言什么&#xff1f;你要去找工作&#xff1f;先別急著找工作&#xff0c;先把下面的python面試題先給看了吧&#xff0c;不然你就只是去面試而不是找工作。話說不打沒準備的仗&#xff0c;下面這些基本的面試題都不會你怎么可能找到工作呢&#xff1f;還是先把下面的東西1、P…

【swift學習筆記】三.使用xib自定義UITableViewCell

使用xib自定義tableviewCell看一下效果圖 1.自定義列 新建一個xib文件 carTblCell&#xff0c;拖放一個UITableViewCell,再拖放一個圖片和一個文本框到tableviewcell上 并給我們的xib一個標識 為了學習&#xff0c;我這里的xib和后臺的class是分開建的。我們再建一個cocoa touc…

leetcode455. 分發餅干(貪心算法)

假設你是一位很棒的家長&#xff0c;想要給你的孩子們一些小餅干。但是&#xff0c;每個孩子最多只能給一塊餅干。對每個孩子 i &#xff0c;都有一個胃口值 gi &#xff0c;這是能讓孩子們滿足胃口的餅干的最小尺寸&#xff1b;并且每塊餅干 j &#xff0c;都有一個尺寸 sj 。…

slack 使用說明_我如何使用Node和Botkit構建HR Slack Bot

slack 使用說明為什么要創建Slack Bot&#xff1f; (Why create a Slack Bot ?) I am an HR professional. More specifically I am a Human Resources Information System (HRIS) Consultant. I work with Application Tracking Systems, Learning Management Systems, and C…

linux 監聽數據包,linux下網絡監聽與發送數據包的方法(即libpcap、libnet兩種類庫的使用方法)...

linux下可以用libpcap函數庫實現監聽數據包&#xff0c;使用libnet 函數庫發送數據包安裝:在命令行下apt-get install 就可以了libpcap的使用:/*author hjjdate 2011-1-21function:capture packet with the ruler and output the packet informationmodify 2011-1-23function:g…

命令模式(Command Pattern)

1命令模式是一個高內聚的模式。定義如下&#xff1a;將一個請求封裝成一個對象&#xff0c;從而讓你使用不同的請求把客戶端參數化&#xff0c;對請求排隊或者記錄請求日志&#xff0c;可以提供命令的撤銷和恢復功能。 2.角色說明&#xff1a; ● Receive接收者角色 該角色就…

BZOJ 3270: 博物館

傳送門 顯然可以狀態轉移&#xff1a; 設 $f[k][x][y]$ 表示第 $k$ 時刻&#xff0c;第一個人在 $x$ &#xff0c;第二個人在 $y$ 時的概率 那么轉移顯然&#xff1a; $f[k][x][y]\sum_{u}\sum_{v}f[k-1][u][v]*(1-P_u)(1-P_v)/du[u]/du[v]$ 其中 $u$ 和 $x$ 有邊相連&#xff…

graphpad7.04多組比較p值_同是折線圖為何你卻這么優秀,這才是多組數據作圖應該有的樣子...

相信大家對Excel做折線圖應該不陌生&#xff0c;在展示數據的時候&#xff0c;圖表是一種最好的展示方法。但是經常會碰到一種尷尬的事情就是&#xff0c;當數據維多比較多的時候&#xff0c;做出的圖表就會顯得非常難看。今天我們就來學習一下&#xff0c;多組數據怎么做折線圖…

Logic-算法-八個箱子找一個最輕的

ylbtech-Arithmetic:Logic-算法-八個箱子找一個最輕的-- -- ylb&#xff1a;算法-- Type:算法[logic]-- munu:八個箱子-找一個最輕的-- thankyou:gaoZhimin -- 7:11 2012/3/17-- 有八個正方形的箱子&#xff0c;外觀大小都一樣&#xff0c;其中七個是50斤的&#xff0c;一個是…

由衷的信來激勵有抱負的開發人員

by Logan Wright洛根賴特(Logan Wright) 由衷的信來激勵有抱負的開發人員 (A heartfelt letter to inspire the aspiring developer) I’m writing a letter to my friend. You should read it. He studies Computer Science, and he hates it. I build React Apps and I love…

linux 運行 chom,Hadoop安裝-單節點/偽分布(2.7.3)

1&#xff0c;下載Hadoop目前在Ubuntu的軟件庫里面 沒有發現Hadoop的壓縮包&#xff0c;沒猜錯Hadoop不是可執行文件 只是一個壓縮包吧&#xff01;所以我們只能自己到官網下載(http://hadoop.apache.org/releases.html)&#xff1b;在Apache社區中&#xff0c;下載軟件的時候…