JavaScript 數(shù)據(jù)類型詳解
一,數(shù)據(jù)類型
以下內(nèi)容基于ES5(ES6引入了一種新的原始數(shù)據(jù)類型Symbol,表示獨(dú)一無二的值。它是JavaScript語言的第七種數(shù)據(jù)類型。)
JavaScript是一種弱類型動(dòng)態(tài)語言,定義變量時(shí)無需指定類型,看似簡單,但背后有繁瑣的轉(zhuǎn)換邏輯。讓我們一起來看下js常見的數(shù)據(jù)類型和背后的隱式轉(zhuǎn)換邏輯。
ES5中有5種簡單的數(shù)據(jù)類型(也叫基本數(shù)據(jù)類型):number,string,boolean,null,undefined(null和undefined是兩種特殊的基本數(shù)據(jù)類型,下面會(huì)講到);還有一種復(fù)雜數(shù)據(jù)類型——Object(函數(shù)是一種特殊的對象,后面會(huì)講到)
Undefined類型:
Undefined類型只有一個(gè)值,即特殊的undefined。在使用var聲明變量但未對其加以初始化時(shí),這個(gè)變量的值就是undefined,例如:
var message; alert(message == undefined);//true
這個(gè)例子只聲明了變量message,但未對其進(jìn)行初始化。比較這個(gè)變量與undefined字面量,結(jié)果表明它們是相等的。這個(gè)例子與下面的例子是等價(jià)的:
var message = undefined; alert(message == undefined);//true
這個(gè)例子是用undefined值顯示初始化了變量message.但我們沒有必要這么做,因?yàn)槲唇?jīng)初始化的值默認(rèn)都會(huì)取得undefined值。
(一般而言,不存在需要顯示地把一個(gè)變量設(shè)置為undefined值的情況。字面值undefined的主要目的是用于比較,而ECMA-262第3版之前的版本中并沒有規(guī)定這個(gè)值。第3版引入這個(gè)值是為了正式區(qū)分空對象指針與未經(jīng)初始化的變量。)
不過,包含undefined值的變量與尚未定義的變量還是不一樣的。請看下面的例子:
var message;//這個(gè)變量聲明之后默認(rèn)取得了undefined值 //下面這個(gè)變量并沒有聲明 //var age alert(message);//'undefined' alert(age);//產(chǎn)生錯(cuò)誤 Uncaught ReferenceError: age is not defined(…)
運(yùn)行以上代碼,第一個(gè)警告框會(huì)顯示變量message的值,即'undefined'。而第二個(gè)警告框由于傳遞給alert()函數(shù)的是尚未聲明的變量age,則會(huì)導(dǎo)致一個(gè)錯(cuò)誤。對于尚未聲明過的變量,只能執(zhí)行一項(xiàng)操作,即使用typeof操作符檢測其數(shù)據(jù)類型。
然而,令人困惑的是:對未初始化的變量執(zhí)行typeof操作符會(huì)返回undefined值,而對未聲明的變量執(zhí)行typeof操作符同樣也會(huì)返回undefined值。來看下面的例子:
var message;//這個(gè)變量聲明之后默認(rèn)取得了undefined值 //下面這個(gè)變量并沒有聲明 //var age alert(typeof message);//'undefined' alert(typeof age);//'undefined'
結(jié)果表明,對未初始化和未聲明的變量執(zhí)行typeof操作符都返回了undefined值,這個(gè)結(jié)果有其邏輯上的合理性,因?yàn)殡m然這兩種變量從技術(shù)角度看有本質(zhì)區(qū)別,但實(shí)際上無論對哪種變量也不可能執(zhí)行真正的操作。
(即使未初始化的變量會(huì)自動(dòng)被賦予undefined值,但我們?nèi)匀唤ㄗh讀者養(yǎng)成顯式初始化變量-即在聲明變量的同時(shí)給變量賦值的習(xí)慣。如果能夠做到這一點(diǎn),那么當(dāng)typeof操作符返回undefined值時(shí),我們就知道被檢測的變量是還沒有被聲明的,而不是尚未初始化的了。)
Null類型
Null類型是第二個(gè)只有一個(gè)值的數(shù)據(jù)類型,這個(gè)特殊的值就是null。從邏輯角度來看,null值表示一個(gè)空對象指針,而這也正是typeof操作符檢測null值會(huì)返回'Object'的原因,如下面的例子所示:
var car = null; alert(typeof car);//'object'
如果定義的變量準(zhǔn)備在將來用于保存對象,那么最好將該變量初始化為null而不是其他值。這樣一來,只要直接檢查null值就可以知道相應(yīng)的變量是否已經(jīng)保存了一個(gè)對象的引用了,如下面的例子所示:
if(car != null){ //對car執(zhí)行某些操作 }
實(shí)際上,undefined值是派生自null值的,因此ECMA-262規(guī)定對它們的相等性測試要返回true;
alert(null == undefined);//'true'
這里,位于null和undefined之間的相等操作符(==)總是返回true,不過要注意的是,這個(gè)操作符出于比較的目的會(huì)轉(zhuǎn)換其操作數(shù)(后面會(huì)詳細(xì)介紹相關(guān)內(nèi)容)。
盡管null和udefined有這樣的關(guān)系,但它們的用途完全不同。如前所述,無論在什么情況下,都沒有必要把一個(gè)變量的值顯式地設(shè)置為undefined,可是同樣的規(guī)則對null卻不適用。換句話說,只要意在保存對象的變量還沒有真正保存對象,就應(yīng)該明確地讓該變量保存null值。這樣做不僅可以體現(xiàn)null作為空對象指針的慣例,而且也有助于進(jìn)一步區(qū)分null和undefined。
二,隱式轉(zhuǎn)換
+和-
在js中,雖然我們不需要顯式地定義變量的類型,但在實(shí)際的處理中,會(huì)根據(jù)不同的類型,會(huì)有不同的處理。先看幾個(gè)例子:
var x = 'The answer is ' + 42;//"The answer is 42" 這里的'+'會(huì)理解為字符串拼接 var y = 42 + ' is the answer';//"42 is the answer" 這里的'+'會(huì)理解為字符串拼接 '37' + 7;//"377" 這里的'+'會(huì)理解為字符串拼接 '37' - 7;//30 這里的'-'會(huì)理解為減法運(yùn)算
我們也可以巧用類型轉(zhuǎn)換,去做一些事情,比如想把一個(gè)變量num轉(zhuǎn)換為數(shù)字類型,非常簡單的辦法就是減去數(shù)字‘0',如果想把一個(gè)變量num變?yōu)樽址愋?,那么可以加上一個(gè)空字符串''。
var num; num = num - 0; alert(typeof num);//"number" num = num + ''; alert(typeof num);//"string"
===
嚴(yán)格等于a===b,首先會(huì)判斷等號(hào)兩邊的類型,如果兩邊的類型不同,直接返回false,不再往下進(jìn)行,如果類型相同,判斷值是否想等。需注意NaN和任何東西比較都不想等,包括和自己比較也不想等。另外,JavaScript中的對象的比較是用引用去比較,而不是用值去比較,所以比較兩個(gè)對象也不相等,因?yàn)椴皇莾蓚€(gè)完全相同的對象??梢远x變量x(不區(qū)分類型),讓x和x比較,返回true。
'1.23' === '1.23';//true null === null;//true undefined == undefined;//true null === undefined;//false NaN === NaN;//false NaN屬于number值,和任何東西比較都不想等,包括和自己比較也不想等 NaN == NaN;//false NaN屬于number值,和任何東西比較都不想等,包括和自己比較也不想等 [1,2] == [1,2];//false 由于js中對象的比較是用引用去比較,雖然兩邊都是數(shù)組,而且長度一樣、相同的值、相同的順序,也是不等的,因?yàn)椴皇峭耆嗤膶ο蟆? new Object() == new Object();//false 引用比較,兩個(gè)空對象是不同的兩個(gè)對象,不相等。 var x; x === x;//true 定義變量x,,讓x和x比較 返回true
==
如果類型相同,比較方法同'===',如果類型不同,會(huì)嘗試類型轉(zhuǎn)換和比較:
null == undefined //相等 number == string //嘗試把string轉(zhuǎn)換成number再去比較 1.0 == '1.0';//true boolean == ? //無論右邊是什么,會(huì)先把boolean先轉(zhuǎn)換成數(shù)字,true轉(zhuǎn)換成1,false轉(zhuǎn)換成0,然后再去和右邊的比較 true == 1; //true. object == number | string //會(huì)嘗試把對象轉(zhuǎn)換為基本類型再去比較 其他的情況是false. new String('hi') == 'hi';//true new Boolean(false) == 0;//true
三,包裝對象
number,string,boolean這三種基本類型都有對應(yīng)的包裝類型,先看一個(gè)例子:
從上面的例子可以看出,js中當(dāng)把一個(gè)基本類型(比如string類型)嘗試以對象的方式去使用的時(shí)候,比如訪問它的length屬性,或者增加一些屬性的時(shí)候,js會(huì)很智能地把被操作的基本類型轉(zhuǎn)換成對應(yīng)的包裝類型對象,(相當(dāng)于new String()),這個(gè)臨時(shí)包裝對象的內(nèi)容和基本類型的值是一樣的,當(dāng)完成訪問或者屬性設(shè)置的時(shí)候,這個(gè)臨時(shí)包裝對象會(huì)被銷毀掉,所以再去訪問已經(jīng)設(shè)置的屬性,是訪問不到的。number和boolean基本類型轉(zhuǎn)換成包裝類型對象的原理都是一樣的。
var a = 'string';//定義變量a,賦值基本類型'string' alert(a.length);//"6" 創(chuàng)建對應(yīng)的臨時(shí)包裝對象,訪問臨時(shí)包裝對象的length屬性,得到結(jié)果6 a.t = 3;//3,設(shè)置成功后,臨時(shí)對象被銷毀,所以下面alert值是undefined alert(a.t);//"undefined"
var b = 123; b.toString();//"123" 調(diào)用對應(yīng)臨時(shí)包裝對象Number()上的toString()方法,轉(zhuǎn)換成字符串
四,類型檢測
1,最常見的是用typeof操作符,會(huì)返回一個(gè)字符串,適合函數(shù)對象和基本類型的判斷,遇到null失效,會(huì)返回Object。
typeof 100 //"number" 數(shù)值 typeof NaN; //"number" 數(shù)值 typeof Infinity;//"number" 數(shù)值 typeof true //"Boolean" 布爾值 typeof(undefined); //"undefined" 表示這個(gè)值未定義 typeof new Object(); //"object" 對象 typeof [1, 2]; //"object" 數(shù)組是對象,沒有特殊處理 typeof null; //"object" null值表示一個(gè)空對象指針,所以返回Object typeof function //"function" 從技術(shù)角度講,函數(shù)在ECMAScript中是對象,不是一種數(shù)據(jù)類型,然而,函數(shù)也確實(shí)有一些特殊的屬性,因此通過typeof操作符來區(qū)分函數(shù)和其他對象是有必要的
2,如果要判斷對象類型,常用的是instanceof,適合自定義對象,也可以用來檢測原生對象,在不同iframe和window間檢測時(shí)失效,是基于原型鏈去判斷,instanceof原理: 判斷obj對象的原型鏈上是否有右邊的構(gòu)造函數(shù)的prototype屬性,關(guān)于原型鏈,詳見后面篇章。
obj instanceof Object(obj:必須是對象,如果是基本類型,直接會(huì)返回false; Object:必須是函數(shù)對象,或者函數(shù)構(gòu)造器,如果不是,就會(huì)拋出TypeError異常。)
看下簡單的例子
new Object() instanceof Array === false //true [1, 2] instanceof Array === true //true [] instanceof Array===true//true
我們知道,任何一個(gè)構(gòu)造函數(shù),都有一個(gè)prototype對象屬性,這個(gè)對象屬性將用作使用new構(gòu)造函數(shù)這種方式構(gòu)造出的對象的原型。比如Person這個(gè)函數(shù),函數(shù)有prototype屬性. 我們用new Person()去創(chuàng)建Person實(shí)例的時(shí)候,這個(gè)對象實(shí)例就會(huì)有一個(gè)原型指向Person.prototype這個(gè)對象。我們用var bosn=new Student(),創(chuàng)建一個(gè)Student實(shí)例bosn,bosn的原型會(huì)指向它的構(gòu)造器Student的prototype對象屬性。檢測bosn instanceof Person時(shí),bosn.__proto__=Student.prototype,然后原型鏈會(huì)繼續(xù)往上查找,bosn.__proto__.__proto__=person.prototype.就會(huì)返回true。注意,不同window或iframe間的對象類型檢測不能使用instanceof!
3,Object.prototype.toString()判斷類型,適合內(nèi)置對象和基本類型,遇到null和undefined失效,IE6/IE7/IE8返回'[object Object]'
Object.prototype.toString.apply([]);==='[object Array]'; Object.prototype.toString.apply(function(){});==='[object Function]'; Object.prototype.toString.apply(null);==='[object Null]';//IE6/IE7/IE8返回'[object Object]' Object.prototype.toString.apply(undefined);==='[object Undefined]';//IE6/IE7/IE8返回'[object Object]' Object.prototype.toString.apply('123');==="[object String]"; Object.prototype.toString.apply(123);==="[object Number]"; Object.prototype.toString.apply(true);==="[object Boolean]"; Object.prototype.toString.apply(String);==="[object Function]"; Object.prototype.toString.apply(Boolean);==="[object Function]"
4,constructor檢測類型
任何一個(gè)對象都有一個(gè)constructor屬性,繼承自原型,會(huì)執(zhí)向構(gòu)造這個(gè)對象的構(gòu)造函數(shù), constructor可以被改寫,使用時(shí)要小心。
5,duck type檢測類型
比如我們不知道一個(gè)對象是否是數(shù)組,我們可以判斷這個(gè)對象的length是否是數(shù)字,是否有join,push等數(shù)組的函數(shù)方法,通過特征判斷對象是否屬于某些類型,有時(shí)也會(huì)用到。
以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時(shí)也希望多多支持腳本之家!
相關(guān)文章
javascript html實(shí)現(xiàn)網(wǎng)頁版日歷代碼
這篇文章主要介紹了javascript html實(shí)現(xiàn)網(wǎng)頁版日歷代碼,需要的朋友可以參考下2016-03-03Ajax高級(jí)筆記 JavaScript高級(jí)程序設(shè)計(jì)筆記
這篇文章主要介紹了Ajax高級(jí)筆記 JavaScript高級(jí)程序設(shè)計(jì)筆記,需要的朋友可以參考下2017-06-06G6?TreeGraph樹圖節(jié)點(diǎn)懶加載使用場景示例
這篇文章主要為大家介紹了G6?TreeGraph樹圖節(jié)點(diǎn)懶加載使用場景示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10js實(shí)現(xiàn)鼠標(biāo)懸浮給圖片加邊框的方法
這篇文章主要介紹了js實(shí)現(xiàn)鼠標(biāo)懸浮給圖片加邊框的方法,涉及jquery.insetborder.js中borderEffect方法的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-01-01小程序canvas手寫簽名適配PC實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了小程序canvas手寫簽名適配PC實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04js實(shí)現(xiàn)數(shù)字跳動(dòng)到指定數(shù)字
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)數(shù)字跳動(dòng)到指定數(shù)字,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08