前言
原始類(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)型都具有toString和valueOf屬性。幾乎所有的類(lèi)型對(duì)象比如Number,String,Boolean,Array,Function,Object,Date,RegExp的原型對(duì)象上都有各自的toString或valueOf方法的實(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
以上是Number、String、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