標籤:style blog class code java c
目錄
instanceof
constructor
建構函式名字
鴨式辨型
三種檢測對象的類方式: instanceof、constructor 、建構函式名字
用法如下:
1)instanceof
console.log([1,2,3] instanceof Array);trueconsole.log([1,2,3] instanceof Object);true
儘管建構函式是原型的唯一標識,instanceof運算子的右運算元是建構函式,instanceof實際計算過程中檢測的是對象的繼承關係,而不是檢測的建立對象時的建構函式,只是使用了建構函式作為中介
當然也可以使用isPrototypeOf 來判斷一個對象是否存在於另一對象的原型鏈中,此時不使用建構函式作為中介
var a1 = new Array();console.log(Array.prototype.isPrototypeOf(a1));trueconsole.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
參考:javascript權威指南
http://www.cnblogs.com/pigtail/p/3450852.html