JavaScript隱式類型轉(zhuǎn)換
JavaScript的數(shù)據(jù)類型是非常弱的(不然不會(huì)叫它做弱類型語(yǔ)言了)!在使用算術(shù)運(yùn)算符時(shí),運(yùn)算符兩邊的數(shù)據(jù)類型可以是任意的,比如,一個(gè)字符串可以和數(shù)字相加。之所以不同的數(shù)據(jù)類型之間可以做運(yùn)算,是因?yàn)镴avaScript引擎在運(yùn)算之前會(huì)悄悄的把他們進(jìn)行了隱式類型轉(zhuǎn)換的,如下是數(shù)值類型和布爾類型的相加:
3 + true; // 4
結(jié)果是一個(gè)數(shù)值型!如果是在C或者Java環(huán)境的話,上面的運(yùn)算肯定會(huì)因?yàn)檫\(yùn)算符兩邊的數(shù)據(jù)類型不一致而導(dǎo)致報(bào)錯(cuò)的!但是,在JavaScript中,只有少數(shù)情況下,錯(cuò)誤類型才會(huì)導(dǎo)致出錯(cuò),比如調(diào)用非函數(shù),或者讀取null或者undefined的屬性時(shí),如下:
"hello"(1); // error: not a function
null.x; // error: cannot read property 'x' of null
多數(shù)情況下,JavaScript都不會(huì)出錯(cuò)的,而是自動(dòng)的進(jìn)行相應(yīng)的類型轉(zhuǎn)換。比如-, *, /,和%等算術(shù)運(yùn)算符都會(huì)把操作數(shù)轉(zhuǎn)換成數(shù)字的,但是“+”號(hào)就有點(diǎn)不一樣了,有些情況下,它是算術(shù)加號(hào),有些情況下,是字符串連接符號(hào),具體的要看它的操作數(shù),如下:
2 + 3; // 5
"hello" + " world"; // "hello world"
但是,如果字符串和數(shù)字相加,會(huì)是怎樣的結(jié)果呢?JavaScript會(huì)自動(dòng)把數(shù)字轉(zhuǎn)換成字符的,不管數(shù)字在前還是字符串在前,如下:
"2" + 3; // "23"
2 + "3"; // "23"
字符串和數(shù)字相加結(jié)果是字符串,字符串和數(shù)字相加結(jié)果是字符串,字符串和數(shù)字相加結(jié)果是字符串,重要的事情說(shuō)三遍?。。。。?!
此外,需要注意的是,“+”的運(yùn)算方向是從左到右的,如下:
1 + 2 + "3"; // "33"
這與下面是等價(jià)的:
(1 + 2) + "3"; // "33"
相比之下,下面的結(jié)果是不一樣的:
1 + "2" + 3; // "123"
但是,隱式類型轉(zhuǎn)換,有時(shí)候,會(huì)隱藏一些錯(cuò)誤的,比如,null會(huì)轉(zhuǎn)換成0,undefined會(huì)轉(zhuǎn)換成NaN。需要注意的是,NaN和NaN是不相等的(這是由于浮點(diǎn)數(shù)的精度決定的),如下:
var x = NaN;
x === NaN; // false
雖然,JavaScript提供了isNaN來(lái)檢測(cè)某個(gè)值是否為NaN,但是,這也不太精確的,因?yàn)?,在調(diào)用isNaN函數(shù)之前,本身就存在了一個(gè)隱式轉(zhuǎn)換的過(guò)程,它會(huì)把那些原本不是NaN的值轉(zhuǎn)換成NaN的,如下:
isNaN("foo"); // true
isNaN(undefined); // true
isNaN({}); // true
isNaN({ valueOf: "foo" }); // true
上面代碼,我們使用isNaN來(lái)測(cè)試后,發(fā)現(xiàn)字符串,undefined,甚至對(duì)象,結(jié)果都返回真!?。〉?,我們總不能說(shuō)他們也是NaN吧?總而言之,得出的結(jié)論是:isNaN檢測(cè)NaN并不可靠?。?!
幸運(yùn)的是,有一種可靠的并且準(zhǔn)確的方法可以檢測(cè)NaN。我們都知道,只有NaN是自己不等自己的,那么,我們就以使用不等于號(hào)(!==)來(lái)判斷一個(gè)數(shù)是否等于自身,從而,可以檢測(cè)到NaN了,如下:
var a = NaN; a !== a; // true var b = "foo"; b !== b; // false var c = undefined; c !== c; // false var d = {}; d !== d; // false var e = { valueOf: "foo" }; e !== e; // false
我們也可以把這種模式定義成一個(gè)函數(shù),如下:
function isReallyNaN(x) { return x !== x; }
OK,NaN的檢測(cè)方法就是這么簡(jiǎn)單,我們下面繼續(xù)討論對(duì)象的隱式轉(zhuǎn)換!
對(duì)象是可以轉(zhuǎn)換成原始值的,最常見(jiàn)的方法就是把它轉(zhuǎn)換成字符串,如下:
"the Math object: " + Math; // "the Math object: [object Math]" "the JSON object: " + JSON; // "the JSON object: [object JSON]"
對(duì)象轉(zhuǎn)換成字符串是調(diào)用了他的toSting函數(shù)的,你可以手動(dòng)的調(diào)用它來(lái)檢測(cè)一下:
Math.toString(); // "[object Math]" JSON.toString(); // "[object JSON]"
類似的,對(duì)象也是可以轉(zhuǎn)換成數(shù)字的,他是通過(guò)valueOf函數(shù)的,當(dāng)然,你也是可以自定義這個(gè)valueOf函數(shù)的,如下:
"J" + { toString: function() { return "S"; } }; // "JS" 2 * { valueOf: function() { return 3; } }; // 6
如果,一個(gè)對(duì)象同時(shí)存在valueOf方法和toString方法,那么,valueOf方法總是會(huì)被優(yōu)先調(diào)用的,如下:
var obj = { toString: function() { return "[object MyObject]"; }, valueOf: function() { return 17; } }; "object: " + obj; // "object: 17"
但是,多數(shù)情況下,這都不是我們想要的,一般的,盡可能使valueOf和toString表示的值相同(盡管類型可以不同)。
最后一種強(qiáng)制類型轉(zhuǎn)換,我們常常稱之為“真值運(yùn)算”,比如,if, ||, &&,他們的操作數(shù)不一定是布爾型的額。JavaScript會(huì)通過(guò)簡(jiǎn)單的轉(zhuǎn)換規(guī)則,將一些非布爾類型的值轉(zhuǎn)換成布爾型的。大多數(shù)的值都會(huì)轉(zhuǎn)換成true,只有少數(shù)的是false,他們分別是:false, 0, -0, ”", NaN, null, undefined,因?yàn)榇嬖跀?shù)字和字符串以及對(duì)象的值為false,所以,直接用真值轉(zhuǎn)換來(lái)判斷一個(gè)函數(shù)的參數(shù)是否傳進(jìn)來(lái)了,這是不不太安全的。比如,有一個(gè)可以具有默認(rèn)值得可選參數(shù)的函數(shù),如下:
function point(x, y) { if (!x) { x = 320; } if (!y) { y = 240; } return { x: x, y: y }; }
這個(gè)函數(shù)會(huì)忽略任何的真值為假的參數(shù)的,包括0,-0;
point(0, 0); // { x: 320, y: 240 }
檢測(cè)undefined的更加準(zhǔn)確的方法是用typeof操作:
function point(x, y) { if (typeof x === "undefined") { x = 320; } if (typeof y === "undefined") { y = 240; } return { x: x, y: y }; }
這種寫(xiě)法,可以區(qū)分開(kāi)0和undefined的:
point(); // { x: 320, y: 240 } point(0, 0); // { x: 0, y: 0 }
另外一種方法是利用參數(shù)跟undefined作比較,如下:
if (x === undefined) { ... }
總結(jié):
1. 類型錯(cuò)誤有可能會(huì)被類型轉(zhuǎn)換所隱藏。
2. “+”既可以表示字符串連接,又可以表示算術(shù)加,這取決于它的操作數(shù),如果有一個(gè)為字符串的,那么,就是字符串連接了。
3. 對(duì)象通過(guò)valueOf方法,把自己轉(zhuǎn)換成數(shù)字,通過(guò)toString方法,把自己轉(zhuǎn)換成字符串。
4.具有valueOf方法的對(duì)象,應(yīng)該定義一個(gè)相應(yīng)的toString方法,用來(lái)返回相等的數(shù)字的字符串形式。
5.檢測(cè)一些未定義的變量時(shí),應(yīng)該使用typeOf或者與undefined作比較,而不應(yīng)該直接用真值運(yùn)算。
關(guān)于JavaScript隱式類型轉(zhuǎn)換就給大家介紹到這里,希望對(duì)大家有所幫助!
- 淺析JavaScript中的隱式類型轉(zhuǎn)換
- 總結(jié)Javascript中的隱式類型轉(zhuǎn)換
- 對(duì)存在JavaScript隱式類型轉(zhuǎn)換的四種情況的總結(jié)(必看篇)
- JavaScript中運(yùn)算符規(guī)則和隱式類型轉(zhuǎn)換示例詳解
- JS面試題大坑之隱式類型轉(zhuǎn)換實(shí)例代碼
- 有趣的JavaScript隱式類型轉(zhuǎn)換操作實(shí)例分析
- JavaScript隱式類型轉(zhuǎn)換代碼實(shí)例
- JavaScript隱式類型轉(zhuǎn)換例子總結(jié)
- 淺析JavaScript中的隱式類型轉(zhuǎn)換
- JavaScript 隱式類型轉(zhuǎn)換規(guī)則詳解
- JS不同運(yùn)算符下隱式類型轉(zhuǎn)換的實(shí)現(xiàn)示例
相關(guān)文章
通過(guò)微信公眾平臺(tái)獲取公眾號(hào)文章的方法示例
這篇文章主要介紹了通過(guò)微信公眾平臺(tái)獲取公眾號(hào)文章的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12Webpack實(shí)現(xiàn)按需打包Lodash的幾種方法詳解
這篇文章主要給大家介紹了關(guān)于Webpack實(shí)現(xiàn)按需打包Lodash的幾種方法,文中介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-05-05使用layui+ajax實(shí)現(xiàn)簡(jiǎn)單的菜單權(quán)限管理及排序的方法
今天小編就為大家分享一篇使用layui+ajax實(shí)現(xiàn)簡(jiǎn)單的菜單權(quán)限管理及排序的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09JS表單驗(yàn)證方法實(shí)例小結(jié)【電話、身份證號(hào)、Email、中文、特殊字符、身份證號(hào)等】
這篇文章主要介紹了JS表單驗(yàn)證方法,結(jié)合實(shí)例形式總結(jié)分析了常用的表單驗(yàn)證技巧,包括電話、身份證號(hào)、Email、中文、特殊字符、身份證號(hào)等驗(yàn)證方法,需要的朋友可以參考下2017-02-02JS實(shí)現(xiàn)IE狀態(tài)欄文字縮放效果代碼
這篇文章主要介紹了JS實(shí)現(xiàn)IE狀態(tài)欄文字縮放效果代碼,涉及JavaScript針對(duì)瀏覽器的相關(guān)調(diào)用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10純js實(shí)現(xiàn)瀑布流布局及ajax動(dòng)態(tài)新增數(shù)據(jù)
這篇文章主要介紹了基于javascript實(shí)現(xiàn)瀑布流布局,及ajax動(dòng)態(tài)新增數(shù)據(jù)的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-04-04