1. 程式人生 > >從toString()方法到Object.prototype.toString.call()方法

從toString()方法到Object.prototype.toString.call()方法

多層 對象 == 上下文 原生 原型繼承 null 之一 我們

一、toString方法和Object.prototype.toSting.call()的區別

var arr=[1,2];

直接對一個數組調用toString()方法,

console.log(arr.toString()); //輸出1,2 現在通過call方法指定arr數組為Object.prototype對象中的toString方法的上下文。 console.log(Object.prototype.toString.call(arr)); //輸出[Object Array] 錯誤理解:按照arr是Object對象的子集,應該toString()方法會繼承下來,所以兩個得到的結果應該是一樣的,但是現實是殘酷的。 原因:Object.prototype的toString方法確實被繼承下來了,但是很多東西總不會一層不變,作為兒子的數組重寫了toString方法,所以直接調用數組對象上面的toString方法調用到的實際是重寫後的方法,並不是Object.prototype中的toString方法。Array,Function等類型作為Object的實例,都重寫了toString方法,不同的對象類型調用toString()方法時,根據原型鏈的知識,調用的是重寫之後的toString方法(函數返回的是函數體內的字符串,Array返回的是元素組成的字符串) 應用場景:Object.prototype對象上的toString方法可以用來判斷數據類型 例如:Object.prototype.toString.call(arr); 輸出:[Object Array] 判斷是否是數組 例子2: var arr=[1,2,3]; console.log(Array.prototype hasOwnPrototype(‘toString‘)) //true console.log(arr.toString()) //1,2,3 delete Array.prototype.toString; //delete操作符可以刪除實例屬性 console.log(Array.prototype hasOwnPrototype(‘toString‘)) //false console.log(arr.toString()) //[object Array]; 刪除了Array的toString方法後,同樣采用arr.toString()方法調用,不再屏蔽Object原型方法的實例方法,arr最後調用了Object的toString方法。 而重寫後的toString方法可以把對象轉換成字符串,還可以把數值轉換成不同進制的數字 [1,2].toString();//1,2 得到字符串 (10).toString(2) //十進制轉二進制,輸出1010,如果10.toString(2)會報錯,因為js會認為.是數字的小數點而不是調用符號。 二、為什麽用Object.prototype.toString.call(obj)檢測對象類型?
第一種:用typeof判斷 我們知道typeof可以檢測數據類型,對變量或值調用typeof運算符將返回下列值之一: undefined->Undefined boolean->Boolean number->Number string->String object->是引用類型或null類型。 function->function函數 typeof檢測引用類型或null是不能準確區分arr json等引用類型的。 那我們還知道一種檢測方式instanceof,來檢測某個對象是不是另一個對愛心那個的實例 第二種:用instanceof判斷 instanceof運算符用來測試一個對象在其原型鏈中是否存在一個構造函數的prototype屬性。 主要用來檢測引用類型,判斷Array和RegExp,無法準確判斷Function. console.log([] instanceof Array) //true console.log({} instanceof Object) //true console.log(/\d/ instanceof RegExp) //true console.log(function(){} instanceof Object) //true console.log(function(){} instanceof Function) //true console.log(‘‘ instanceof String) //false console.log(1 instanceof Number) //false var a=new Array(); alert(a instanceof Array); 同時alert(a instanceof Object)也會返回true,因為Array是object的子類。 function test(){} var a=new test(); alert(a instanceof test);會返回true. alert(a==b) //false; 另外,更重要的一點是instanceof可以在繼承關系中用來判斷一個實例是否屬於他的父類型。 function Foo(){} Foo.prototype=new Aoo() //js原型繼承 var foo= new Foo(); console.log(foo instanceof Foo) //true console.log(foo.instanceof Aoo) //true 上面代碼中是判斷了一層繼承關系的父類,在多層繼承關系中,isntanceof運算符同樣適用。 //定義構造函數 function C(){} function D(){} var o=new C(); o instanceof C //true o instanceof D //false 因為D.prototype不在o的原型鏈上 o instanceof Object //true 因為Object.prototype.isPrototypeOf(o) 返回true C.prototype instanceof Object //true 同上 C.prototype={} var o2=new C(); o2 instanceof C //true o instanceof C //false C。prototype指向了一個空對象,這個空對象不在o的原型鏈上。 D.prototype =new C(); //繼承 var o3=new D(); o3 instanceof D //true o3 isntanceof C //true 談到instanceof 我們要多插入一個問題,就是function的arguments,我們大家也許認為arguments是一個Array,但如果用instanceof去測試回發現arguments不是一個Array對象,盡管看起來很像。 第三種:Object.prototype.toString 這是對象的一個原生擴展函數,用來精確區分數據類型 var type=Object.prototype.toString console.log(type.call(‘‘)) //object String console.log(type.call([])) //object Array console.log(type.call({})) //object Object console.log(type.call(false)) //object Boolean console.log(type.call(null)) //object Null console.log(type.call(undefined)) //object Undefined console.log(type.call(function(){})) //object Function

從toString()方法到Object.prototype.toString.call()方法