js類型判斷及鴨式辨型

來源:互聯網
上載者:User

標籤: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

 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.