valueof 和toString

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)換nullundefined值,也可以說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ī)則如下:

  1. 如果toString方法存在并且返回“原始類型”,返回toString的結(jié)果。
  2. 如果toString方法不存在或者返回的不是“原始類型”,調(diào)用valueOf方法,如果valueOf方法存在,并且返回“原始類型”數(shù)據(jù),返回valueOf的結(jié)果。
  3. 其他情況,拋出錯(cuò)誤。
Number轉(zhuǎn)換

當(dāng)需要使用Number時(shí),( 如Math.sin() )等,解釋器會(huì)嘗試將對(duì)象轉(zhuǎn)換成Number對(duì)象。
通常有如下的情況會(huì)觸發(fā)Number轉(zhuǎn)換

  1. 方法參數(shù)需要Number的時(shí)候,如Math.sin(obj)等
  2. 對(duì)比的時(shí)候,如 obj == 'abc'
  3. 運(yùn)算的時(shí)候,如 obj + 123

轉(zhuǎn)換規(guī)則如下:

  1. 如果valueOf存在,且返回“原始類型”數(shù)據(jù),返回valueOf的結(jié)果。
  2. 如果toString存在,且返回“原始類型”數(shù)據(jù),返回toString的結(jié)果。
  3. 報(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上陣了。

最后編輯于
?著作權(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),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執(zhí)行單位為行(line),也就是一...
    悟名先生閱讀 4,503評(píng)論 0 13
  • 第5章 引用類型(返回首頁) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,663評(píng)論 0 4
  • 一直都喜歡寫點(diǎn)什么 一直都在寫日記 沒記錯(cuò)是從初中開始吧 還是為了寫給初戀 就這樣一直寫到了現(xiàn)在 期間也斷過 今晚...
    GGFFYY閱讀 219評(píng)論 0 0
  • 處處天生就是逃避專業(yè)戶,尤其和感情有關(guān)的問題,處處在感情上一直比較被動(dòng),基本上是走配合對(duì)方的路線,從感情一開始考慮...
    星座先森閱讀 1,193評(píng)論 0 1

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