JavaScript隱式類(lèi)型轉(zhuǎn)換例子總結(jié)
前言
熟練掌握類(lèi)型轉(zhuǎn)換,理解其中的規(guī)律。可以讓你的代碼更簡(jiǎn)潔更安全。
在編寫(xiě)代碼的時(shí)候,我們通常會(huì)有意無(wú)意的寫(xiě)出一些,存在類(lèi)型轉(zhuǎn)換的代碼。這些代碼有時(shí)的返回值總讓人迷惑,比如下列式子都是我們工作中常見(jiàn)的:
var a = 1; var b = '2'; var c = a + b; // '12'; var d = 43; d == '43'; // true d === '43'; // false
上面都是比較常見(jiàn)的,讓我們?cè)倏磶讉€(gè)例子:
// 例子1 const obj = { toString() { return : 'xxx'; } } const obj2 = {}; obj.toString(); // "xxx" 當(dāng)然,我們還是可以使用Object.prototype.toString.call(obj)的,因?yàn)檫@是調(diào)用了Object對(duì)象,但是如果改寫(xiě)了Object的toString方法,那情況就不一樣了。 obj2.toString(); // "[object Object]" // 例子2 const a = [1,2,3]; const b = [4,5]; a + b; // "1,2,34,5" // 例子3 false == []; // true false == ""; // true false == null; // false false == undefined; // false [] == ![]; // true
看到上面的結(jié)果,是否你也感覺(jué)頭疼。現(xiàn)在讓我們開(kāi)始探索,看看這中間都發(fā)生了怎樣的類(lèi)型轉(zhuǎn)換。
在講強(qiáng)制類(lèi)型轉(zhuǎn)換是我們先思考一個(gè)問(wèn)題,不同的數(shù)據(jù)類(lèi)型值都會(huì)發(fā)生什么類(lèi)型轉(zhuǎn)換?在什么情況下會(huì)發(fā)生類(lèi)型轉(zhuǎn)換?具體是怎么轉(zhuǎn)換的?
發(fā)生了類(lèi)型轉(zhuǎn)換通常都是操作值做了【抽象操作】(ES5規(guī)范第9節(jié)中定義了一些“僅供內(nèi)部使用的操作”)。這里我們簡(jiǎn)單介紹一下ToString
,ToNumber
,ToBoolean
同時(shí)還有一個(gè)ToPrimitive
。
ToString
ToString
是對(duì)非字符串進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換。
- 對(duì)于基本數(shù)據(jù)類(lèi)型,ToString則是進(jìn)行字符串化,null轉(zhuǎn)化為"null",undefined轉(zhuǎn)化為"undefined",true轉(zhuǎn)化為"true"。對(duì)于數(shù)字的ToString,需要注意的是,數(shù)字的極大值跟極小值會(huì)轉(zhuǎn)為指數(shù)形式表示。
var a = 1.07 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000; a.toString(); // "1.07e21";
- 對(duì)于引用數(shù)據(jù)類(lèi)型的ToString,通常會(huì)調(diào)用引用對(duì)象中的 toString()進(jìn)行轉(zhuǎn)化,如果對(duì)象沒(méi)有這個(gè)方法則會(huì)發(fā)生報(bào)錯(cuò)。(注意:從ES5開(kāi)始,使用Objest.create(null)創(chuàng)建的對(duì)象,因?yàn)閯?chuàng)建對(duì)象的
[[Prototype]]
為null,所以不會(huì)有toString()和valueOf()這兩個(gè)方法)。
var a = [1,2,3,4]; a.toString(); // "1,2,3,4" var b = { a: 42, foo: 'foo' } b.toString(); // "[object Object]"
ToNumber
- 對(duì)基本數(shù)據(jù)類(lèi)型,ToNumber跟調(diào)用Number轉(zhuǎn)數(shù)字一樣。
Number(true); // 1 Number(false); // 0 Number(null); // 0 Number(undefined); // NaN Number(""); // 0 Number("123"); // 123 Number("123aaa"); // NaN
- 對(duì)于引用數(shù)據(jù)類(lèi)型,會(huì)先判斷對(duì)象是否有valueOf(),如果有則將返回的值進(jìn)行類(lèi)型轉(zhuǎn)換。如果沒(méi)有,則判斷是否有toSrting(),并將其返回值做類(lèi)型轉(zhuǎn)換。如果這兩個(gè)方法都沒(méi)有則報(bào)錯(cuò)TypeError。
var a = { valueOf() { return "42"} }; var b = { toString() { return "42"} }; var c = [1,2]; c.toString = function() { return this.join(""); } Number(a); // 42 Number(b); // 42 Number(c); // 12 Number([]); // 0 Number([1,2]); // NaN
ToBoolean
對(duì)于抽象操作ToBoolean
,ES5規(guī)范9.2中列出一些假值,既對(duì)這些值進(jìn)行布爾強(qiáng)制類(lèi)型轉(zhuǎn)換時(shí),會(huì)轉(zhuǎn)為false的值。除了這些值以外,所有值進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換時(shí),都會(huì)得到true。
undefined null "" // 空字符串 +0, -0, NaN false
ToPrimitive
抽象操作ToPrimitive
,其實(shí)在ToSting
,ToNumber
,ToBoolean
獲取對(duì)象原始值的時(shí)候,就是通過(guò)ToPrimitive
來(lái)獲取的,獲取完原始值之后,再進(jìn)行toString(),Number(),Boolean()等類(lèi)型轉(zhuǎn)換。
總結(jié),在對(duì)值進(jìn)行類(lèi)型轉(zhuǎn)換時(shí),如果是基本數(shù)據(jù)類(lèi)型,則直接對(duì)使用該值進(jìn)行類(lèi)型轉(zhuǎn)換;如果是引用類(lèi)型,會(huì)先通過(guò)ToPrimitive
獲取原始值,然后使用獲取的原始值進(jìn)行類(lèi)型轉(zhuǎn)換。
而之前說(shuō)的【先檢查對(duì)象是否包含valueOf()
,如果沒(méi)有在檢查toString()
】這個(gè)過(guò)程就是 ToPrimitive
。
現(xiàn)在我們分析完類(lèi)型轉(zhuǎn)換的過(guò)程都具體做了什么操作了,現(xiàn)在我們看下,在那些操作下會(huì)發(fā)生類(lèi)型轉(zhuǎn)換。
運(yùn)算符 +
如果操作數(shù)中存在字符串,則進(jìn)行字符串拼接;如果操作數(shù)是對(duì)象,則會(huì)對(duì)對(duì)象進(jìn)行 ToPrimitive
抽象操作以獲取原始值,通常這操作都會(huì)獲取到字符串。最后進(jìn)行 + 操作。
var a = [1,2]; var b = [3,4]; a + b; // "1,23,4"
邏輯判斷相關(guān)
- if(..)
- while(..)和do..while(..)
- 三元表達(dá)式 ?:
- for(..; ..; ..){}
- 邏輯或|| 和 邏輯與&& 左邊的操作數(shù)
上面的語(yǔ)句中所包含的判斷表達(dá)式,都會(huì)將非布爾值通過(guò)抽象操作ToBoolean
,將值轉(zhuǎn)為boolean。
== 寬松對(duì)等規(guī)則
1. 字符串和數(shù)字之間的相等比較
- 如果Type(x)是數(shù)字,Type(y)是字符串,則返回 x === ToNumber(y)的結(jié)果。
- 如果Type(x)是字符串,Type(y)是數(shù)字,則返回 ToNumber(x) === y的結(jié)果。
var x = 42; var y = '42'; x === y; // false x == y; // true 這里轉(zhuǎn)換為: 42 == ToNumber('42') => true
2. 其他類(lèi)型和布爾類(lèi)型的相等比較
- 如果Type(x)是布爾類(lèi)型,則返回 ToNumber(x) === y 的結(jié)果。
- 如果Type(y)是布爾類(lèi)型,則返回 x === ToNumber(y)的結(jié)果。
var x = true; var y = '42' x === y; // false x == y; // false // false 這里轉(zhuǎn)換為:toNumber(true) == toNumber('42') => 1 == 42 => false
3. null 和 undefined 之間的相等比較
- 如果x為null,y為undefined,則結(jié)果為true。
- 如果x為undefined,y為true,則結(jié)果為true。
注意: 在 == 中null和undefined相等(也與自身相等),除此之外其他值都不和他們相等。 所以可以使用一特性,對(duì)值進(jìn)行判斷是否等于null或undefined
var x = null; var y; x === y; // false x == y; //true
4. 對(duì)象和非對(duì)象之間的相等比較
- 如果Type(x)是字符串或數(shù)字,Type(y)是對(duì)象,則返回 x == ToPrimitive(y)的結(jié)果。
- 如果Type(y)是字符串或數(shù)字,Type(x)是對(duì)象,則返回 ToPrimitive(x) == y的結(jié)果。
var a = 42 var b = [42] a == b; // true // [42]調(diào)用ToPrimitive,返回"42",變成 "42" == 42,然后又變成 42 == 42,最后兩者相等。 var a = "abc"; var b = Object(a); // new String( a )一樣 a === b; // false a == b; // true
這里有些值不一樣
var a = null; var b = Object(a); // 和Object()一樣 a == b; // false var c = undefined; var d = Object(c); // 和Object()一樣 c == d; // false var e = NaN; var f = Object(e); // 和new Number(e) 一樣 e == f; // NaN == NaN => false
因?yàn)閖s中,沒(méi)有undefined 和 null 對(duì)應(yīng)的封裝對(duì)象。所以對(duì)他們進(jìn)行Object封裝跟調(diào)用Object()一樣,返回一個(gè)常規(guī)對(duì)象。
而NaN是因?yàn)椋琋aN本身就不等于自己。
總結(jié)
總的來(lái)說(shuō):在寬松對(duì)比中,對(duì)比的值具有這樣的轉(zhuǎn)換優(yōu)先級(jí),對(duì)象 > 非對(duì)象(非對(duì)象中:字符串,布爾都會(huì)ToNumber轉(zhuǎn)為數(shù)字,進(jìn)行比較)
。同時(shí)需要注意 NaN(唯一不等于自己的值),undefined和null這幾個(gè)值的轉(zhuǎn)換。
當(dāng)然,寬松對(duì)等中不同值對(duì)比,才會(huì)進(jìn)行類(lèi)型轉(zhuǎn)換。如果是相同類(lèi)型的比較,不會(huì)進(jìn)行類(lèi)型轉(zhuǎn)換。"0" == "" 返回false
。因?yàn)檫@是字符串"0"
和""
的對(duì)比,不會(huì)進(jìn)行抽象操作ToNumber
。
理解了對(duì)象的類(lèi)型轉(zhuǎn)換都是ToPrimitive
操作,那么我們需要注意,任何情況下都不要重寫(xiě)對(duì)象的 valueOf()
和toString()
方法。
到此這篇關(guān)于JavaScript隱式類(lèi)型轉(zhuǎn)換例子總結(jié)的文章就介紹到這了,更多相關(guān)JS隱式轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 淺析JavaScript中的隱式類(lèi)型轉(zhuǎn)換
- JavaScript隱式類(lèi)型轉(zhuǎn)換
- 總結(jié)Javascript中的隱式類(lèi)型轉(zhuǎn)換
- 對(duì)存在JavaScript隱式類(lèi)型轉(zhuǎn)換的四種情況的總結(jié)(必看篇)
- JavaScript中運(yùn)算符規(guī)則和隱式類(lèi)型轉(zhuǎn)換示例詳解
- JS面試題大坑之隱式類(lèi)型轉(zhuǎn)換實(shí)例代碼
- 有趣的JavaScript隱式類(lèi)型轉(zhuǎn)換操作實(shí)例分析
- JavaScript隱式類(lèi)型轉(zhuǎn)換代碼實(shí)例
- 淺析JavaScript中的隱式類(lèi)型轉(zhuǎn)換
- JavaScript 隱式類(lèi)型轉(zhuǎn)換規(guī)則詳解
- JS不同運(yùn)算符下隱式類(lèi)型轉(zhuǎn)換的實(shí)現(xiàn)示例
相關(guān)文章
javascript獲取當(dāng)前鼠標(biāo)坐標(biāo)的方法
這篇文章主要介紹了javascript獲取當(dāng)前鼠標(biāo)坐標(biāo)的方法,可針對(duì)不同瀏覽器獲取鼠標(biāo)的坐標(biāo)位置,是非常實(shí)用技巧,需要的朋友可以參考下2015-01-01詳解基于webpack2.x的vue2.x的多頁(yè)面站點(diǎn)
本篇文章主要主要介紹了基于webpack2.x的vue2.x的多頁(yè)面站點(diǎn) ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-08-08詳解微信小程序膠囊按鈕返回|首頁(yè)自定義導(dǎo)航欄功能
對(duì)于一些電商平臺(tái)來(lái)說(shuō),當(dāng)商品被轉(zhuǎn)發(fā)后會(huì)很影響客戶查看其它產(chǎn)品和首頁(yè),這時(shí)候就需要使用自定義導(dǎo)航欄自己寫(xiě)一個(gè)“膠囊按鈕”。這篇文章主要介紹了詳見(jiàn)微信小程序膠囊按鈕返回|首頁(yè)自定義導(dǎo)航欄,需要的朋友可以參考下2019-06-06JS實(shí)現(xiàn)復(fù)制內(nèi)容到剪貼板功能
本文主要介紹了JS實(shí)現(xiàn)復(fù)制內(nèi)容到剪貼板功能的步驟方法,可兼容所有PC瀏覽器,不兼容手機(jī)端。具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02JS實(shí)現(xiàn)仿google、百度搜索框輸入信息智能提示的實(shí)現(xiàn)方法
這篇文章主要介紹了JS實(shí)現(xiàn)仿google、百度搜索框輸入信息智能提示的實(shí)現(xiàn)方法,實(shí)例分析了javascript實(shí)現(xiàn)智能提示功能的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04微信小程序開(kāi)發(fā)教程-手勢(shì)解鎖實(shí)例
手勢(shì)解鎖是app上常見(jiàn)的解鎖方式,相比輸入密碼方式操作起來(lái)要方便許多。這篇文章主要介紹了微信小程序開(kāi)發(fā)教程-手勢(shì)解鎖實(shí)例,有興趣的可以了解一下。2017-01-01