三種檢測對象的類方式: instanceof、constructor 、建構函式名字 用法如下: 1)instanceof console.log([1,2,3] instanceof Array);true console.log([1,2,3] instanceof Object);true儘管建構函式是原型的唯一標識,instanceof運算子的右運算元是建構函式,instanceof實際計算過程中檢測的是對象的繼承關係,而不是檢測的建立對象時的建構函式,只是使用了建構函式作為中介 當然也可以使用isPrototypeOf 來判斷一個對象是否存在於另一對象的原型鏈中,此時不使用建構函式作為中介 var a1 = new Array();console.log(Array.prototype.isPrototypeOf(a1));true console.log(Array.prototype.isPrototypeOf([1,2,3]));true注意:多個執行內容時(例如存在不同架構時)instanceof使用有限制 2)constructor 每個javascript函數都可以用作建構函式,調用建構函式需要使用prototype屬性,因而每個javascript函數會自動擁有prototype屬性,這個屬性值是一個對象,這個對象包含一個contructor屬性,constructor屬性值是一個函數對象。 即對於函數var F = function(){}; F.prototype.constructor===F 關係圖如下: eg: 複製代碼var F= function(){};var p = F.prototype;var c = p.constructor;console.log(p);console.log(c);console.log(c===F); Object {}function (){}true複製代碼因而對象繼承的constructor均指代他們的建構函式 eg: var o= new F();console.log(o.constructor===F); //輸出 true var a = new Array();console.log(a.constructor===Array);//輸出true 複製代碼function typeDiscern(x){ switch(x.constructor){ case Number: return "Number:"+x; case String: return "String:"+x; case Array: return "Array:"+x; }}console.log(typeDiscern([1,2,3]));console.log(typeDiscern("abc"));console.log(typeDiscern(5));//輸出Array:1,2,3String:abcNumber:5複製代碼 注意: 同instanceof在多個上下文下沒法使用,另外並不是所有的對象都包含constructor屬性 eg: 定義Person類 複製代碼function Person(name) { this.name=name; this.getName=function() { return this.name; } }; var wish=new Person('js'); console.log(wish.constructor==Person); console.log(Person.prototype);console.log(Person.constructor); console.log(wish.getName()); //輸出truePerson {}function Function() { [native code] }js複製代碼 給Person自訂prototype 複製代碼function Person(name) { this.name=name; this.getName=function() { return this.name; } }; Person.prototype={ toString: function(){ return this.name; }}; var wish=new Person('js'); console.log(wish.constructor==Person); console.log(Person.prototype);console.log(Person.constructor); console.log(wish.getName());console.log(wish.toString()); //輸出falseObject {toString: function}function Function() { [native code] }jsjs複製代碼此時新定義的原型對象不含有constructor屬性,因而Person的執行個體也不包含constructor屬性 解決方案:可顯示的給原型添加構造方法 Person.prototype={ constructor=Person, toString: function(){ return this.name; }}; 建構函式名字 沒有intanceof和constructor的執行內容問題,一個視窗中的Array建構函式和另一個視窗內Array建構函式不等,但是建構函式名字相同,但是並不是每個函數都有名字 複製代碼Function.prototype.getName= function(){ if("name" in this){ return this.name; } return this.name=this.toString().match(/function\s*([^(]*)/);}function test1(){}console.log(test1.getName()); //輸出:test1複製代碼 鴨式辨型 關注對象能做什麼,而不是對象的類是什麼 James Whitcomb Riley提出像鴨子一樣走路、遊泳和嘎嘎叫的鳥就是鴨子 主要對象包含walk(),swim(),bike()這三個方法就可以作為參數傳入 利用鴨式辯型實現的函數: 複製代碼function quackImplements(o/*,...*/){ for(var i=1; i<arguments.length;i++){ var arg=arguments[i]; switch(typeof arg){ case 'string': if(typeof o[arg]!=="function") return false; continue; case 'function': arg=arg.prototype; case 'object': for (var m in arg){ if(typeof arg[m]!=="function") continue; if(typeof o[m]!=="function") return false; } } } return true;}複製代碼對於字串直接檢查命名方法 對於對象檢查是否有同名方法 對於函數檢查建構函式的原型對象中是否有相同方法 在javascript中很多函數都不對對象做類型檢測只是關心這些對象能做什麼 eg:Array的prototype利用了鴨式辨型,arguments是偽數組 複製代碼 (function () { var arr = Array.prototype.slice.apply(arguments); console.log(arr);})(1, 2, 3); //輸出:[1, 2, 3]複製代碼 var arr = Array.prototype.slice.apply({ 0: 1, 1: 2, 2: 3, length: 3 }); console.log(arr); //輸出:[1, 2, 3] 使用鴨式辨型可以擴大對象的使用範圍 eg:讓普通對象具有數組的push方法 複製代碼Function.prototype.unCurrying = function () { var f = this; return function () { var a = arguments; return f.apply(a[0], [].slice.call(a, 1)); };};Function.prototype.unCurrying = function () { return this.call.bind(this);}; var push = Array.prototype.push.unCurrying(),obj = {};push(obj, 'first', 'two');console.log(obj);console.log("length:"+obj.length)複製代碼 輸出: Object{0: "first", 1: "two", length: 2}length:2