在進行數(shù)據(jù)轉(zhuǎn)化時,所有對象繼承了兩個轉(zhuǎn)換方法:
toString():返回一個反映這個對象的字符串窍育;
valueOf():返回它相應(yīng)的原始值溶褪。
1、toString()
當(dāng)對象表示為文本值時或期望以字符串的方式引用對象時丹锹,該方法被自動調(diào)用。對象obj在調(diào)用toString() 返回形如:[object type]芬失。其中type是對象類型楣黍。如果obj不是對象,toString() 返回obj應(yīng)有的文本值(不是單純的加”“)棱烂。
let obj ={};
console.log(obj.toString());//[object Object]
console.log(obj.toString.call(new String));//[object String]
console.log(obj.toString.call(new Date));//[object Date]
console.log(obj.toString.call(new Array));//[object Array]
console.log(obj.toString.call(new Number));//[object Number]
console.log(obj.toString.call(Function));//[object Function]
console.log(obj.toString.call(Math));//[object Math]
console.log(obj.toString.call(undefined));//[object Undefined]
console.log(obj.toString.call(null));//[object Null]
-----------------------------------------------------------------------------
let objArr = [1, 2, 3, 4, 5];
console.log(objArr.toString());//1,2,3,4,5
let arr =[{id:123,name:'ShangSan'},'2',3,true];
console.log(arr.toString());//[object Object],2,3,,true
let objNum = 12345;
console.log(objNum.toString());//12345
let objBoolean=true;
console.log(objBoolean.toString());//true
let objFunc = function () {
console.log('param');
}
console.log(objFunc.toString());
// function () {
// console.log('param');
// }
也可以復(fù)寫這個方法(自定義這個方法租漂,這個方法沒有參數(shù)且必須有個返回值)。
let obj = {
toString:function(){
return '我是toString方法';
}
};
console.log(obj.toString());//我是toString方法
console.log(obj.toString.call(new String));//我是toString方法
不同類型對象的toString()方法的返回值
對象 | 返回值 |
---|---|
Array | 返回數(shù)組字符串颊糜,字符串以逗號隔開,如:"1,2,3,4" 哩治,空數(shù)組為空字符串 |
Boolean | 布爾字符串,"false" 和"true"
|
Date | 現(xiàn)在時間字符串衬鱼,如:"Thu Jul 25 2019 14:35:20 GMT+0800 (中國標(biāo)準時間)"
|
Function | 函數(shù)本身字符串 |
Number | 數(shù)字字符串 |
Object | "[object Object]" |
String | 字符串值 |
2业筏、valueOf()
JavaScript 調(diào)用 valueOf() 方法用來把對象轉(zhuǎn)換成原始類型的值(數(shù)值、字符串和布爾值) 鸟赫。默認情況下, valueOf() 會被每個對象Object繼承蒜胖。每一個內(nèi)置對象都會覆蓋這個方法為了返回一個合理的值,如果對象沒有原始值抛蚤,valueOf() 就會返回對象自身台谢。
不同類型對象的valueOf()方法的返回值
對象 | 返回值 |
---|---|
Array | 返回數(shù)組對象本身 |
Boolean | 布爾值 |
Date | 存儲的時間是從 1970 年 1 月 1 日午夜開始計的毫秒數(shù) UTC |
Function | 函數(shù)本身 |
Number | 數(shù)字值 |
Object | 對象本身,這是默認情況 |
String | 字符串值 |
//let objArr = [1, 2, 3, 4, 5];
let objArr = ['a', 'b', 'c', 'd', 'f'];
console.log(objArr.valueOf());//["a", "b", "c", "d", "f"]
let objBoolean = true;
console.log(objBoolean.valueOf());//true
let objDate = new Date();
console.log(objDate.valueOf());//1555381853497
let objFunc = function () {
console.log('param');
}
console.log(objFunc.valueOf());
// ? () {
// console.log('param');
// }
let objNum = 12345;
console.log(objNum.valueOf());//12345
let obj = {
id: '1001',
age: 19
};
console.log(obj.valueOf());//{id: "1001", age: 19}
let objStr = new String('abcdfe');
console.log(objStr.valueOf());//abcdfe
也可以復(fù)寫這個方法(自定義這個方法岁经,這個方法沒有參數(shù)且必須有個返回值)朋沮。
let obj = {
valueOf:function(){
return '我是valueOf方法';
}
};
console.log(obj.valueOf());//我是valueOf方法
console.log(obj.valueOf.call(new String));//我是valueOf方法
那么問題來了,對象何時調(diào)用 toString(),何時調(diào)用 valueOf()缀壤?樊拓??
3诉位、優(yōu)先級
我們下面通過實例還說明骑脱,先定義一個基礎(chǔ)的對象obj,復(fù)寫toString()和valueOf()方法苍糠。
let obj = {
toString: function () {
console.log('調(diào)用了 obj.toString');
return {};
},
valueOf: function () {
console.log('調(diào)用了 obj.valueOf')
return 123;
}
}
3.1 直接輸出對象
直接 alert(obj)叁丧,輸出:調(diào)用了 obj.toString ;調(diào)用了 obj.valueOf。
修改toString返回值為基礎(chǔ)數(shù)據(jù)類型拥娄,valueOf返回值保持不變蚊锹。
obj.toString = function () {
console.log('調(diào)用了 obj.toString');
return 'aaa'
};
alert(obj),輸出:調(diào)用了 obj.toString 稚瘾。并沒有調(diào)用valueOf()牡昆。
得出結(jié)論:
直接輸出對象時,先調(diào)用其toString方法摊欠,若toString返回原始值就直接返回丢烘,否則繼續(xù)調(diào)用valueOf方法,若valueOf返回不是原始類型些椒,報錯播瞳。
注意:由于這種場景先調(diào)用toString,在調(diào)用valueOf免糕,若調(diào)用valueOf返回值為對象赢乓,會報錯。(所以就不舉例說明toString和valueOf返回都為對象的情況了)
3.2 對象參與運算
直接 alert(obj+‘1’)/ alert(obj+1)/alert(obj+true);石窑,輸出:只調(diào)用了 obj.valueOf牌芋。
直接 alert(obj==‘1’),輸出:只調(diào)用了 obj.valueOf松逊。
修改valueOf返回值為對象躺屁,toString返回值保持不變。
obj.valueOf = function () {
console.log('調(diào)用了 obj.valueOf');
return [];
}
alert(obj+1)棺棵,輸出:調(diào)用了 obj.valueOf楼咳。調(diào)用了 obj.toString 熄捍。并且報錯Uncaught TypeError: Cannot convert object to primitive value烛恤。
修改valueOf返回值為對象,再修改toString返回值為基礎(chǔ)數(shù)據(jù)類型余耽。
obj.toString = function () {
console.log('調(diào)用了 obj.toString');
return 'aaa';
}
obj.valueOf = function () {
console.log('調(diào)用了 obj.valueOf');
return [];
}
alert(obj+1)缚柏,輸出:調(diào)用了 obj.valueOf。調(diào)用了 obj.toString 碟贾。不報錯币喧。
得出結(jié)論:
對象參與運算時,先調(diào)用其valueOf方法袱耽,若valueOf返回原始值就直接返回杀餐,否則繼續(xù)調(diào)用toString方法,若toString返回不是原始類型朱巨,報錯史翘。
另外注意,===運算,倆個都不調(diào)用琼讽,是個例外必峰。
終上所述,這兩個方法在不同使用場景會有不同的優(yōu)先級:
正常情況下钻蹬,
優(yōu)先調(diào)用toString()吼蚁,有運算操作符的情況下valueOf()的優(yōu)先級高于toString();
當(dāng)調(diào)用valueOf()方法無法運算后還是會再調(diào)用toString()方法;
當(dāng)調(diào)用toString()方法無法的的原始類型后還是會再調(diào)用valueOf()方法问欠。