- JavaScript重難點實例精講
- 周雄
- 2361字
- 2020-10-30 15:51:55
1.5 toString()函數與valueOf()函數
在1.4.1小節關于等于運算符的內容中,如果比較的內容包含對象類型數據,則會涉及隱式轉換,那么就會調用toString()函數和valueOf()函數。本節會詳細講解toString()函數與valueOf()函數,并通過實例來看看它們的使用場景。
在JavaScript中,toString()函數與valueOf()函數解決的是值的顯示和運算的問題,所有引用類型都擁有這兩個函數。
1. toString()函數
toString()函數的作用是把一個邏輯值轉換為字符串,并返回結果。Object類型數據的toString()函數默認的返回結果是"[object Object]",當我們自定義新的類時,可以重寫toString()函數,返回可讀性更高的結果。
在JavaScript中,Array,Function,Date等類型都實現了自定義的toString()函數。
· Array的toString()函數返回值為以逗號分隔構成的數組成員字符串,例如[1, 2,3].toString()結果為字符串'1,2,3'。
· Function的toString()函數返回值為函數的文本定義,例如(function(x){return x *2;}).toString()的結果為字符串"function(x){return x * 2;}"。
· Date的toString()函數返回值為具有可讀性的時間字符串,例如,new Date().toString()的結果為字符串"Sun Nov 25 2018 15:00:16 GMT+0800 (中國標準時間)"。
2. valueOf()函數
valueOf()函數的作用是返回最適合引用類型的原始值,如果沒有原始值,則會返回引用類型自身。Object類型數據的valueOf()函數默認的返回結果是"{}",即一個空的對象字面量。
對于Array、Function、Date等類型,valueOf()函數的返回值是什么呢?
· Array的valueOf()函數返回的是數組本身,例如[1, 2, 3].valueOf()返回的結果為“[1,2,3]”。
· function的valueOf()函數返回的是函數本身,例如(function(x){return x * 2;}).valueOf()返回的結果為函數本身“function(x){return x * 2;}”。
· Date的valueOf()函數返回的是指定日期的時間戳,例如new Date().valueOf()返回的結果為“1543130166771”。
如果一個引用類型的值既存在toString()函數又存在valueOf()函數,那么在做隱式轉換時,會調用哪個函數呢?
這里我們可以概括成兩種場景,分別是引用類型轉換為String類型,以及引用類型轉換為Number類型。
1. 引用類型轉換為String類型
一個引用類型的數據在轉換為String類型時,一般是用于數據展示,轉換時遵循以下規則。
· 如果對象具有toString()函數,則會優先調用toString()函數。如果它返回的是一個原始值,則會直接將這個原始值轉換為字符串表示,并返回該字符串。
· 如果對象沒有toString()函數,或者toString()函數返回的不是一個原始值,則會再去調用valueOf()函數,如果valueOf()函數返回的結果是一個原始值,則會將這個結果轉換為字符串表示,并返回該字符串。
· 如果通過toString()函數或者valueOf()函數都無法獲得一個原始值,則會直接拋出類型轉換異常。
我們通過以下代碼進行測試。
var arr = []; arr.toString = function () { console.log('執行了toString()函數'); return []; }; arr.valueOf = function () { console.log('執行了valueOf()函數'); return []; }; console.log(String(arr));
上面代碼執行后的結果如下所示。
執行了toString()函數 執行了valueOf()函數 TypeError: Cannot convert Object to primitive value
執行String(arr)代碼時,需要將arr轉換為字符串,則會優先執行toString()函數,但是其返回值為空數組[],并不能轉換為原生數據;然后調用valueOf()函數,其返回值同樣為空數組[];那么在調用完toString()函數和valueOf()函數后,均無法獲取到原生數據類型表示,則拋出異常TypeError,表示無法將對象類型轉換為原生數據類型。
2. 引用類型轉換為Number類型
一個引用類型的數據在轉換為Number類型時,一般是用于數據運算,轉換時遵循以下規則。
· 如果對象具有valueOf()函數,則會優先調用valueOf()函數,如果valueOf()函數返回一個原始值,則會直接將這個原始值轉換為數字表示,并返回該數字。
· 如果對象沒有valueOf()函數,或者valueOf()函數返回的不是原生數據類型,則會再去調用toString()函數,如果toString()函數返回的結果是一個原始值,則會將這個結果轉換為數字表示,并返回該數字。
· 如果通過toString()函數或者valueOf()函數都無法獲得一個原始值,則會直接拋出類型轉換異常。
我們通過以下代碼進行測試。
var arr = []; arr.toString = function () { console.log('執行了toString()函數'); return []; }; arr.valueOf = function () { console.log('執行了valueOf()函數'); return []; }; console.log(Number(arr));
上面代碼執行后的結果如下所示。
執行了valueOf()函數 執行了toString()函數 TypeError: Cannot convert Object to primitive value
執行Number(arr)代碼時,需要將arr轉換為數字,則會優先執行valueOf()函數,但是其返回值為空數組[],并不能轉換為原生數據;然后調用toString()函數,其返回值同樣為空數組[];那么在調用完valueOf()函數和toString()函數后,均無法獲取到原生數據表示,則拋出異常TypeError,表示無法將對象類型轉換為原生數據類型。
事實上,對除了Date類型以外的引用類型數據轉換為原生數據類型時,如果是用于數據運算,則會優先調用valueOf()函數,在valueOf()函數無法滿足條件時,則會繼續調用toString()函數,如果toString()函數也無法滿足條件,則會拋出類型轉換異常。
如果是用于數據展示,則會優先調用toString()函數,在toString()函數無法滿足條件時,則會繼續調用valueOf()函數,如果valueOf()函數也無法滿足條件,則會拋出類型轉換異常。
了解了valueOf()函數和toString()函數的關系后,我們再用下面兩組代碼深入拓展一下其他相關知識。
拓展1
看看下面3行代碼,它們的結果有什么不同。
[] == 0; // true [1] == 1; // true [2] == 2; // true
在第一行中,空數組可以轉換為數字0;在第二行和第三行中,只有一個數字元素的數組可以轉換為該數字。這是為什么呢?
因為數組繼承了Object類型默認的valueOf()函數,這個函數返回的是數組自身,而不是原生數據類型,所以會繼續調用toString()函數。數組調用toString()函數時會返回數組元素以逗號作為分隔符構成的字符串,那么空數組就轉換為空字符串,而空字符串與數字0在非嚴格相等的情況下是相等的,即'' == 0,返回“true”。
同樣,只包含一個數字的數組[1],轉換后為字符串"1",后判斷"1" == 1,返回“true”。
拓展2
以下是另外一組Object類型的數據,請觀察結果有什么不同。
var obj = { i: 10, toString: function () { console.log('toString'); return this.i; }, valueOf: function () { console.log('valueOf'); return this.i; } }; +obj; // valueOf '' + obj; // valueOf String(obj); // toString Number(obj); // valueOf obj == '10'; // valueOf,true obj === '10'; // false
第一行執行代碼為+obj,將對象obj轉換為原始值,用于數據運算,優先調用valueOf()函數,獲得原始值,結果為數字“10”。
第二行執行代碼為'' + obj,將對象obj轉換為原始值,用于數據運算,優先調用valueOf()函數,獲取原始值,并與字符串進行拼接,結果為字符串"10"。
第三行執行代碼為String(obj),在String()函數中,用于數據展示,優先調用toString()函數獲取對象的字符串表示,結果為字符串"10"。
第四行執行代碼為Number(obj),將對象obj轉換為數值表示,用于數據運算,優先調用valueOf()函數,結果為數字“10”。
第五行執行代碼為obj == '10',將對象obj轉換為原始值,用于數據運算,優先調用valueOf()函數,即將10與'10'進行比較,兩者是相等的,結果為“true”;
第六行執行代碼為obj === '10',因為兩者數據類型不一致,直接返回“false”,并不會執行toString()函數或者valueOf()函數。
- Python概率統計
- Web Scraping with Python
- Learning C++ Functional Programming
- Web交互界面設計與制作(微課版)
- 技術領導力:程序員如何才能帶團隊
- Practical Windows Forensics
- Securing WebLogic Server 12c
- Visual Basic程序設計
- Django 3.0入門與實踐
- Raspberry Pi Robotic Blueprints
- PrimeFaces Blueprints
- Python 3 Object:oriented Programming(Second Edition)
- 深入解析Java編譯器:源碼剖析與實例詳解
- 邊玩邊學Scratch3.0少兒趣味編程
- 實驗編程:PsychoPy從入門到精通