var a = new String( "abc" );的值應(yīng)當(dāng)是什么。
a是一個(gè)對(duì)象。一個(gè)基本類型值的封裝對(duì)象。
typeof a; // 是"object",不是"String"
a instanceof String; // true
Object.prototype.toString.call( a ); // "[object String]"

通過構(gòu)造函數(shù)(如 new String("abc"))創(chuàng)建出來的是封裝了基本類型值(如 "abc")的封 裝對(duì)象。
我們比較準(zhǔn)確的判斷一個(gè)類型的方法為
Object.prototype.toString(..)這是因?yàn)樗?typeof 返回值為 "object" 的對(duì)象,都有一個(gè)內(nèi)部屬性 [[Class]],這個(gè)屬性無法直接訪問,一般通過
Object.prototype.toString(..)來查看,一般對(duì)象的內(nèi)部 [[Class]] 屬性和創(chuàng)建該對(duì)象的內(nèi)建原生構(gòu)造函數(shù)相對(duì)應(yīng)。除了null 和 undefined,因?yàn)?p>
Object.prototype.toString.call( null ); // "[object Null]"
Object.prototype.toString.call( undefined ); // "[object Undefined]"
雖然 Null() 和 Undefined() 這樣的原生構(gòu)造函數(shù)并不存在,但是內(nèi)部 [[Class]] 屬性值仍 然是 "Null" 和 "Undefined"。我們至少可以準(zhǔn)確判斷出類型。
為什么 "abc" 可以有.length等屬性?
封裝對(duì)象(object wrapper)扮演著十分重要的角色。由于基本類型值沒有 .length 和 .toString() 這樣的屬性和方法,需要通過封裝對(duì)象才能訪問,此時(shí) JavaScript 會(huì)自動(dòng)為 基本類型值包裝(box 或者 wrap)一個(gè)封裝對(duì)象:
一般情況下,我們不需要直接使用封裝對(duì)象。最好的辦法是讓 JavaScript 引擎自己決定什 么時(shí)候應(yīng)該使用封裝對(duì)象。換句話說,就是應(yīng)該優(yōu)先考慮使用 "abc" 和 42 這樣的基本類型 值,而非new String("abc")和new Number(42)。
如果想要得到封裝對(duì)象中的基本類型值,可以使用 valueOf() 函數(shù):
var a = new String( "abc" );
var b = new Number( 42 );
var c = new Boolean( true );
a.valueOf(); // "abc"
b.valueOf(); // 42
c.valueOf(); // true
在需要用到封裝對(duì)象中的基本類型值的地方會(huì)發(fā)生隱式拆封。因?yàn)闆]有new Null()和new Undefined()這樣的封裝器,也就是說他們是沒有對(duì)應(yīng)的封裝對(duì)象。從而沒有對(duì)應(yīng)的valueOf()。
var str1 = 'w3cplus';
var str2 = new String('w3cplus');
typeof(str1); // => string
typeof(str2); // => object
str1 == str2 // => true
str1是一個(gè)String類型,而str2卻是一個(gè)Object類型,但用==比較兩個(gè)變量時(shí),結(jié)果卻為true。這是因?yàn)椋贘avaScript中會(huì)幫我們自動(dòng)轉(zhuǎn)換類型,然后再進(jìn)行比對(duì)。
String(),new String(), toString() 區(qū)別
toString()和String()的主要區(qū)別就在于
String()還能轉(zhuǎn)換null和undefined值,也可以說String()是toString()增強(qiáng)版,在開發(fā)中直接使用String()似乎更好,這樣能避免潛在的轉(zhuǎn)換風(fēng)險(xiǎn)。
toString()和valueOf()作用差不多,都是轉(zhuǎn)換成原始類型的值。
valueOf():返回最適合該對(duì)象類型的原始值;
toString(): 將該對(duì)象的原始值以字符串形式返回。
這兩個(gè)方法一般是交由JS去隱式調(diào)用,以滿足不同的運(yùn)算情況。
在數(shù)值運(yùn)算里,會(huì)優(yōu)先調(diào)用valueOf(),如a + b;
在字符串運(yùn)算里,會(huì)優(yōu)先調(diào)用toString(),如alert(c)。
在JavaScript進(jìn)行對(duì)比或者各種運(yùn)算的時(shí)候會(huì)把對(duì)象轉(zhuǎn)換成Number、String、Boolean這些類型,從而進(jìn)行后續(xù)的操作
String轉(zhuǎn)換
在某個(gè)操作或者運(yùn)算需要字符串的時(shí)候,往往會(huì)觸發(fā)Object的String轉(zhuǎn)換
var obj={name:'Mofei'}
var str = ' ' + obj
console.log(str); // [object Object]
上述的例子中,在字符串相加的過程中,系統(tǒng)調(diào)用了obj的String轉(zhuǎn)換,具體規(guī)則如下:
- 如果toString方法存在并且返回“原始類型”,返回toString的結(jié)果。
- 如果toString方法不存在或者返回的不是“原始類型”,調(diào)用valueOf方法,如果valueOf方法存在,并且返回“原始類型”數(shù)據(jù),返回valueOf的結(jié)果。
- 其他情況,拋出錯(cuò)誤。
Number轉(zhuǎn)換
當(dāng)需要使用Number時(shí),( 如Math.sin() )等,解釋器會(huì)嘗試將對(duì)象轉(zhuǎn)換成Number對(duì)象。
通常有如下的情況會(huì)觸發(fā)Number轉(zhuǎn)換
- 方法參數(shù)需要Number的時(shí)候,如Math.sin(obj)等
- 對(duì)比的時(shí)候,如 obj == 'abc'
- 運(yùn)算的時(shí)候,如 obj + 123
轉(zhuǎn)換規(guī)則如下:
- 如果valueOf存在,且返回“原始類型”數(shù)據(jù),返回valueOf的結(jié)果。
- 如果toString存在,且返回“原始類型”數(shù)據(jù),返回toString的結(jié)果。
- 報(bào)錯(cuò)。
Boolean轉(zhuǎn)換
在進(jìn)行布爾比較的時(shí)候,比如 if(obj) , while(obj)等等,會(huì)進(jìn)行布爾轉(zhuǎn)換,布爾轉(zhuǎn)換遵循如下規(guī)則:
| 值 | 布爾值 |
|---|---|
| true/false | true/false |
| undefined,null | false |
| Number | 0,NaN 對(duì)應(yīng) false, 其他的對(duì)應(yīng) true |
| String | ""對(duì)應(yīng)false,其他對(duì)應(yīng)true('0'對(duì)應(yīng)的是true) |
| Object | true |
JavaScript 對(duì)象轉(zhuǎn)換,toString,valueOf
valueOf()原生實(shí)現(xiàn)
| 數(shù)據(jù)類型 | 返回值 |
|---|---|
| Array | 與 Array.toString 和 Array.join 方法相同 |
| Function | 函數(shù)本身 |
| Date | 毫秒數(shù)UTC |
| Boolean | 布爾值 |
| Number | 數(shù)字值 |
| String | 字符串值 |
| Object | 對(duì)象本身 |
toString()原生實(shí)現(xiàn) 返回的值全部為字符串
| 數(shù)據(jù)類型 | 返回值 |
|---|---|
| Array | 與 Array.valueOf 和 Array.join 方法相同 |
| Function | 獲取函數(shù)源代碼 |
| Object | 返回[object type] |
| Boolean | 布爾值 |
| Date | 格式化日期 |
| String | 字符串值 |
| Number | 數(shù)字值,可以攜帶進(jìn)制參數(shù) |
隱式數(shù)據(jù)轉(zhuǎn)換即為解釋器自發(fā)根據(jù)需要調(diào)用Number(),Boolean()等基本類型轉(zhuǎn)換函數(shù)使結(jié)果符合期待。若參數(shù)為object類型時(shí),調(diào)用ToPrimitive()(假想函數(shù)),該函數(shù)根據(jù)需要的數(shù)據(jù)類型做出的反應(yīng)也不同,若在使用操作符運(yùn)算時(shí)需要number類型則優(yōu)先調(diào)用valueOf(),結(jié)果為NaN再調(diào)用toString()。其他大部分情況需要string類型則優(yōu)先調(diào)用toString()。
toString()和valueOf()的主要不同點(diǎn)在于
1、 toString()返回的是字符串,而valueOf()返回的是基本類型值
2、由于undefined和null不是對(duì)象,所以它們toString()和valueOf()兩個(gè)方法都沒有
3、數(shù)值Number類型的toString()方法可以接收轉(zhuǎn)換基數(shù),返回不同進(jìn)制的字符串形式的數(shù)值;而valueOf()方法無法接受轉(zhuǎn)換基數(shù)
4、時(shí)間Date類型的toString()方法返回的表示時(shí)間的字符串表示;而valueOf()方法返回的是現(xiàn)在到1970年1月1日00:00:00的數(shù)值類型的毫秒數(shù)
5、包裝對(duì)象的valueOf()方法返回該包裝對(duì)象對(duì)應(yīng)的原始值
6、使用toString()方法可以區(qū)分內(nèi)置函數(shù)和自定義函數(shù)
如果只重寫了toString,對(duì)象轉(zhuǎn)換時(shí)會(huì)無視valueOf的存在來進(jìn)行轉(zhuǎn)換。如果只重寫了valueOf方法,在要轉(zhuǎn)換為字符串的時(shí)候會(huì)優(yōu)先考慮toString方法。在不能調(diào)用toString的情況下,只能讓valueOf上陣了。