1.toString()
它的作用是:將某一個(gè)值轉(zhuǎn)化為字符串
我們先看個(gè)demo:
var t1 = {a: 1};
var t2 = [1,2];
var t3 = 'str';
var t4= 5
var t5=true
console.log(t1.toString()) //"[object Object]"
console.log(t2.toString()) //"1,2"
console.log(t3.toString()) // "str"
console.log(t4.toString()) // "4"
console.log(t5.toString()) // "true"
在上面的例子中盏缤,我們定義了對象茫舶、數(shù)組陕习、字符串三個(gè)類型來調(diào)用toString
方法垢夹,但是結(jié)果卻完全不一樣猛拴。奇怪仁热?
從例子上看揍很,
- 對象返回的是貌似可以反映出其類型的字符串
- 數(shù)組返回的是字符串列表
- 字符串返回的是字符串副本(即原樣輸出)
所以從結(jié)果看融柬,貌似不同類型的toString
的方法功能不一樣(雖然名字都叫toString)。
了解過對象原型以及基本包裝類型的朋友都知道煎娇,上面例子中:
- t1調(diào)用的是Object.prototype里的方法
- t2調(diào)用的是Array.prototype里的方法
- t3調(diào)用的是String.prototype里的方法
雖然t2也是對象二庵,但其原型鏈上的第一層Array.prototype就有toString方法
,所以就會(huì)直接繼承缓呛,而不會(huì)再去找Array.prototype.__proto__即Object.prototype中的toString方法
催享,所以不同類型的原型鏈?zhǔn)交蚨嗷蛏俣?重寫了toString方法,所以功能用處都不一樣哟绊。
接下來因妙,我們再來分析一下不同類型調(diào)用toString()方法,返回值有什么不同之處?
1.1.字符串string(即調(diào)用 new String出來的基本包裝類型的方法)
返回字符串的一個(gè)副本(即原樣輸出)
var str = "a";
str.toString(); //"a"
String.prototype.toString.call(str) // "a"
1.2.數(shù)值number(即調(diào)用 new Number出來的基本包裝類型的方法)
返回字符串形式的數(shù)值
var num = 520;
num.toString(); //"520"
Number.prototype.toString.call(num) // "a"
1.3.布爾值boolean(即調(diào)用 new Boolean出來的基本包裝類型的方法)
返回字符串"true"或"false"
var boo = true;
boo.toString(); //"true"
Boolean.prototype.toString.call(boo); //"true"
1.4.獨(dú)一無二值symbol(即調(diào)用構(gòu)造函數(shù)Symbol生成的實(shí)例方法攀涵,注這里調(diào)用和一般的構(gòu)造函數(shù)不一樣铣耘,不需要new,直接調(diào)用)
返回字符串"Symbol()"
var symbol = Symbol();
symbol.toString(); //"Symbol()"
Symbol.prototype.toString.call(symbol); //"Symbol()"
1.5.null和undefined
null和undefined沒有相應(yīng)的構(gòu)造函數(shù)以故,所以它們沒有也無法調(diào)用toString()方法蜗细,也就是說它們不能訪問任何屬性和方法,只是基本類型而已怒详。
16.對象object(即調(diào)用Object.prototype的方法)
返回
[object type]
炉媒,其中type為對象的類型
var t1 = {a: 1};
t1.toString() //"[object Object]"
Object.prototype.toString.call(t1); //"[object Object]"
1.7.數(shù)組Array(即調(diào)用Array.prototype的方法)
返回由數(shù)組中每個(gè)值的字符串形式 拼接而成的一個(gè)以逗號分隔的字符串
var array = [1, 's', true, {a: 2}];
array.toString();//"1,s,true,[object Object]"
Array.prototype.toString.call(array);//"1,s,true,[object Object]"
1.8.函數(shù)function(即調(diào)用Function.prototype的方法)
返回函數(shù)的代碼
function foo(){
console.log(1');
};
foo.toString();
<!--"function foo(){-->
<!-- console.log(1);-->
<!--}"-->
Function.prototype.toString.call(foo);
<!--"function foo(){-->
<!-- console.log(1');-->
<!--}"-->
所以:
Object.toString();
//"function Object() { [native code] }"
Function.toString();
//"function Function() { [native code] }"
Array.toString();
//"function Array() { [native code] }"
....
因?yàn)?/p>
Array.__proto__===Function.prototype //true
Object.__proto__===Function.prototype //true
Function.__proto__===Function.prototype //true
1.9.日期Date(即調(diào)用Date.prototype的方法)
返回帶有時(shí)區(qū)信息的日期和時(shí)間
var date = new Date();
date.toString();
//"Fri May 11 2018 14:55:43 GMT+0800 (中國標(biāo)準(zhǔn)時(shí)間)"
Date.prototype.toString.call(date);
//"Fri May 11 2018 14:55:43 GMT+0800 (中國標(biāo)準(zhǔn)時(shí)間)"
1.10.正則表達(dá)式RegExp(即調(diào)用RegExp.prototype的方法)
返回正則表達(dá)式的字符串形式
var re = /cat/g;
re.toString();// "/cat/g"
RegExp.prototype.toString.call(re);// "/cat/g"
1.11.全局對象window
返回
[object window]
window.toString(); //"[object Window]"
Object.prototype.toString.call(window); //"[object Window]"
window是js中的特殊對象,Window并不是個(gè)構(gòu)造函數(shù)昆烁,也就是說并沒有Window.prototype原型對象上重寫toString()方法吊骤,它會(huì)順著原型鏈查找調(diào)用Object.prototype.toString()。
2.Object.prototype.toString.call( )
上面我們通過直接調(diào)用和call調(diào)用兩種方式進(jìn)行toString
方法測試静尼。我們知道對應(yīng)object返回的結(jié)果是[object type]
白粉,其中type為對象的類型`,那么我們可以根據(jù)其返回對象的功能進(jìn)行類型判斷鼠渺。
Object.prototype.toString.call({});
<!--"[object Object]"-->
Object.prototype.toString.call([]);
<!--"[object Array]"-->
Object.prototype.toString.call(function(){});
<!--"[object Function]"-->
Object.prototype.toString.call('');
<!--"[object String]"-->
Object.prototype.toString.call(1);
<!--"[object Number]"-->
Object.prototype.toString.call(true);
<!--"[object Boolean]"-->
Object.prototype.toString.call(null);
<!--"[object Null]"-->
Object.prototype.toString.call(undefined);
<!--"[object Undefined]"-->
Object.prototype.toString.call();
<!--"[object Undefined]"-->
Object.prototype.toString.call(new Date());
<!--"[object Date]"-->
Object.prototype.toString.call(/at/);
<!--"[object RegExp]"-->
3.直接調(diào)用
toString();
<!--"[object Undefined]"-->
(function(){
console.log(toString());
})();
<!--[object Undefined]-->
也就是說直接調(diào)用toString()方法鸭巴,等價(jià)于
Object.prototype.toString.call();
<!--"[object Undefined]"-->
Object.prototype.toString.call(undefined);
<!--"[object Undefined]"-->
即:直接調(diào)用toString()方法這里不可以理解成為全局作用域調(diào)用toString()方法,即window.toString()
所以直接調(diào)用toString()應(yīng)該就是變相的undefined.toString()方法(這里說的是相當(dāng)于系冗,實(shí)際undefined并沒有方法奕扣,調(diào)用會(huì)報(bào)錯(cuò))。
4.toString.call/apply(類型)
經(jīng)常有人用toString.call/apply(類型)去代替Object.prototype.toString.call/apply(類型)使用掌敬,其實(shí)這樣是不嚴(yán)謹(jǐn)?shù)模菀讓?dǎo)致一些問題池磁,如下所示
function toString(){
console.log(1")
}
toString();//1
toString.call({});//1
toString.call([]);//1
我們可以發(fā)現(xiàn)奔害,當(dāng)我們自定義了toString()方法時(shí),直接調(diào)用toString()方法地熄,就不會(huì)再默認(rèn)調(diào)用Object類的toString()方法华临,而是會(huì)使用我們自定義的方法,這樣可能得不到我們想要的結(jié)果端考,所以我們還是應(yīng)當(dāng)盡量使用Object.prototype.toString.call/apply(類型)雅潭。
5.類型
類似toString()方法,Object的不同子類型還重寫了toLocaleString()却特、valueOf()等方法
扶供,這里我想說的是不管對象子類型怎么重寫方法,只要我們明白這些方法是哪里來的裂明,怎么調(diào)用的椿浓,就能很好的理解這些方法調(diào)用后產(chǎn)生的結(jié)果!
說到底,對JS中對象和原型的理解真的非常非常重要扳碍!
6.參考
由Object.prototype.toString.call( )引發(fā)關(guān)于toString( )方法的思考