深入理解JavaScript中的toString,valueOf屬性

前言

原始類(lèi)型:在javascript中有三種主要的原始類(lèi)型,數(shù)值、字符串、布爾值,當(dāng)使typeof操作符時(shí)分別返回'number'、'string'、'boolean',還有另外兩個(gè)是'undefined''null',其余類(lèi)型都是對(duì)象類(lèi)型。
包裝對(duì)象:可以把原始類(lèi)型的值包裝成對(duì)象,三種原始類(lèi)型的包裝對(duì)象分別為Number、String、Boolean,當(dāng)使用new Number()創(chuàng)建一個(gè)數(shù)字時(shí),typeof操作會(huì)返回'object'而非number,而通過(guò)調(diào)用數(shù)字對(duì)象的valueOf方法可以返回該數(shù)字對(duì)象的原始類(lèi)型的值。由于包裝對(duì)象的存在,原始類(lèi)型也可以調(diào)用包裝對(duì)象上的方法和參數(shù),調(diào)用時(shí)JavaScrip引擎會(huì)自動(dòng)將原始類(lèi)型的值轉(zhuǎn)為包裝對(duì)象實(shí)例,調(diào)用結(jié)束立即銷(xiāo)毀實(shí)例。


一、概述

javascript 中幾乎所有類(lèi)型都具有toStringvalueOf屬性。幾乎所有的類(lèi)型對(duì)象比如Number,String,Boolean,Array,Function,Object,Date,RegExp的原型對(duì)象上都有各自的toStringvalueOf方法的實(shí)現(xiàn),故它們的實(shí)例化的對(duì)象自然就繼承了這兩個(gè)方法。下面看一下這些類(lèi)型的原型對(duì)象上是否有這兩個(gè)方法的實(shí)現(xiàn):

代碼示例:
Number.prototype.hasOwnProperty('toString');    //輸出true
Number.prototype.hasOwnProperty('valueOf');    //輸出true
String.prototype.hasOwnProperty('toString');    //輸出true
String.prototype.hasOwnProperty('valueOf');    //輸出true
Boolean.prototype.hasOwnProperty('toString');    //輸出true
Boolean.prototype.hasOwnProperty('valueOf');    //輸出true
Array.prototype.hasOwnProperty('toString');     //輸出true
Array.prototype.hasOwnProperty('valueOf');     //輸出false 
Function.prototype.hasOwnProperty('toString');     //輸出true
Function.prototype.hasOwnProperty('valueOf');     //輸出false
Object.prototype.hasOwnProperty('toString');     //輸出true
Object.prototype.hasOwnProperty('valueOf');     //輸出true
Date.prototype.hasOwnProperty('toString');     //輸出true
Date.prototype.hasOwnProperty('valueOf');     //輸出true
RegExp.prototype.hasOwnProperty('toString');     //輸出true
RegExp.prototype.hasOwnProperty('valueOf');     //輸出false
說(shuō)明:hasOwnProperty用于查看某個(gè)對(duì)象本身是否具有某屬性,只在對(duì)象本身查找不在該對(duì)象的原型鏈上查找

上面代碼中,只有Array,Function,RegExp的原型上沒(méi)有valueOf屬性,但是為什么其實(shí)例化對(duì)象能調(diào)用該方法呢?我們都知道上面所有列舉的類(lèi)型的原型(prototype)都是繼承于Object的原型(prototype)的,當(dāng)Array,Function,RegExp的實(shí)例化對(duì)象找不到某個(gè)屬性時(shí)會(huì)沿著原型鏈往上找,直到找到或給出undefined。其實(shí)例對(duì)象調(diào)用的是Object原型上的valueOf


二、toString的作用

1.將值轉(zhuǎn)換為字符串形式并返回,不同類(lèi)型的toString方法各有不同

類(lèi)型 toString()的作用
Number 返回文本表示,可接收一個(gè)參數(shù)表示輸出的進(jìn)制數(shù),默認(rèn)為十進(jìn)制,注意:10..toString()會(huì)把第一個(gè).當(dāng)作小數(shù)點(diǎn)
String 直接返回原字符串值
Boolean 返回文本表示'true'或'false'
Object 返回[object 類(lèi)型名],Object類(lèi)型調(diào)用該方法時(shí)返回[object Object]
Array 將數(shù)組元素轉(zhuǎn)換為字符串,用逗號(hào)拼接并返回
Function 直接返回函數(shù)的文本聲明
Date 返回日期的文本表示, eg:'Sat Apr 21 2018 16:07:37 GMT+0800 (中國(guó)標(biāo)準(zhǔn)時(shí)間)'
RegExp 返回文本格式為'/pattern/flag',其中pattern是正則表達(dá)式,flag是匹配模式:g:全局匹配、i:不分大小寫(xiě)、m:多行匹配;eg:'/\[bc\]at/g'

2.判斷對(duì)象的類(lèi)型

代碼示例:
var a = new Object();
a.toString();      //"[object Object]"
a.toString.call(a);  //"[object Object]"
Object.prototype.toString.call(a);  //"[object Object]"
Object.prototype.toString.call(Object); //"[object Function]"
Object.prototype.toString.call(Object.prototype);   //"[object Object]"

上面提到Object.prototype.toString()可以返回"[object 調(diào)用該方法的對(duì)象類(lèi)型]",所以說(shuō)是不是可以通過(guò)這個(gè)方法來(lái)判斷對(duì)象的類(lèi)型。只要讓對(duì)象直接調(diào)用該方法即可,這需要借助Function.prototype.call方法。

Object.prototype.toString.call(1);   //"[object Number]"
Object.prototype.toString.call('2');    //"[object String]"
Object.prototype.toString.call(true);    //"[object Boolean]"
Object.prototype.toString.call([]);      //"[object Array]"
Object.prototype.toString.call(function(){});    //"[object Function]"
Object.prototype.toString.call(new Date());      //"[object Date]"
Object.prototype.toString.call(/^hello world$/);  //"[object RegExp]"

三、valueOf的作用
類(lèi)型 valueOf()的作用
Number 返回原始類(lèi)型的數(shù)字值
String 返回原始類(lèi)型的字符串值
Boolean 返回原始類(lèi)型的Boolean
Object 返回對(duì)象本身
Array 方法繼承于Object.prototype,返回原數(shù)組
Function 方法繼承于Object.prototype,返回函數(shù)本身
Date 方法等同于getTime,返回時(shí)間戳
RegExp 方法繼承于Object.prototype,返回值本身

四、toString和valueOf的關(guān)系

兩者在類(lèi)型轉(zhuǎn)換中扮演著重要的角色,兩者關(guān)系與javascript的類(lèi)型轉(zhuǎn)換息息相關(guān),下面說(shuō)下javascript的類(lèi)型轉(zhuǎn)換及其原則

1.強(qiáng)制轉(zhuǎn)換: Number()、String()、Boolean()

示例://原始類(lèi)型的強(qiáng)制轉(zhuǎn)換
Number(123) // 123
Number('123') // 123
Number('a123b') // NaN
Number('') // 0
Number(true) // 1
Number(false) // 0
Number(undefined) // NaN
Number(null) // 0
String(123) // "123"
String('abc') // "abc"
String(true) // "true"
String(undefined) // "undefined"
String(null) // "null"
//下面5種情況為false,其余情況為true
Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false

以上是NumberString、Boolean、null、undefined對(duì)于原始類(lèi)型的強(qiáng)制轉(zhuǎn)換的規(guī)則,但是當(dāng)Number()、String()遇到對(duì)對(duì)象的強(qiáng)制轉(zhuǎn)換時(shí)情況就不同了,這個(gè)時(shí)候就會(huì)用到toString(),valueOf()方法了。

Number(對(duì)象)
調(diào)用對(duì)象的valueOf方法,若返回原始類(lèi)型的值,則遵照上面的"非對(duì)象強(qiáng)制轉(zhuǎn)換規(guī)則",若還是返
回對(duì)象,則調(diào)用toString方法,若返回原始類(lèi)型的值,則遵照上面的"非對(duì)象強(qiáng)制轉(zhuǎn)換規(guī)則",
若返回對(duì)象則報(bào)錯(cuò)
String(對(duì)象)
調(diào)用對(duì)象的toString方法,若返回原始類(lèi)型的值,則遵照上面的"非對(duì)象強(qiáng)制轉(zhuǎn)換規(guī)則",若還是返
回對(duì)象,則調(diào)用valueOf方法,若返回原始類(lèi)型的值,則遵照上面的"非對(duì)象強(qiáng)制轉(zhuǎn)換規(guī)則",
若返回對(duì)象則報(bào)錯(cuò)

2.自動(dòng)類(lèi)型轉(zhuǎn)換

情況一:兩個(gè)不同類(lèi)型的值進(jìn)行數(shù)值運(yùn)算
情況二:對(duì)非Boolean類(lèi)型進(jìn)行Boolean運(yùn)算
情況三:對(duì)非數(shù)值類(lèi)型使用一元運(yùn)算符(+ 、-)

規(guī)則:預(yù)期什么類(lèi)型的值,就調(diào)用該類(lèi)型的轉(zhuǎn)換函數(shù)。
若預(yù)期為String類(lèi)型的值,那么就用String()來(lái)進(jìn)行強(qiáng)轉(zhuǎn)。
如果該位置即可以是String,也可能是Number,那么默認(rèn)為Number。
一般Number的優(yōu)先級(jí)高于String
//1.二元運(yùn)算符+若有一個(gè)參與運(yùn)算的數(shù)值為String則預(yù)期為String:
'3'+1;  //31
'3' + true // "3true"
'3' + {} // "3[object Object]"
'3' + [] // "3"
'3' + function (){} // "3function (){}"
'3' + undefined // "3undefined"
'3' + null // "3null"
//2.二元運(yùn)算符 - 、* 、/ 預(yù)期一般為Number:
'7' - '2' // 5
'7' * '2' // 14
true - 2  // -1
false - 1 // -1
'3' * []    // 0
false / '3' // 0
'abcd' - 2   // NaN
null + 2 // 2
undefined + 1 // NaN
//3.一元運(yùn)算符預(yù)期為Number:
+'abcde' // NaN
-'abcde' // NaN
+true // 1
-false // 0
參考文章:

JavaScript 標(biāo)準(zhǔn)參考教程(alpha)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容