javascript
《JS权威指南学习总结--9.5 类和类型》
內(nèi)容要點:
??? 介紹了三種用以檢測任意對象的類的技術(shù),instanceof運算符、constructor屬性,以及構(gòu)造函數(shù)的名字。
??? 但每種技術(shù)都不甚完美,本節(jié)總結(jié)了鴨式辯型,這種編程哲學(xué)更加關(guān)注對象可以完成什么工作(它包含什么方法)而不是對象屬于哪個類
?一.instanceof運算符
???? 1.左操作數(shù)是帶檢測其類的對象,右操作數(shù)是定義類的構(gòu)造函數(shù)。如果o繼承自c.prototype,則表達(dá)式 o instanceof c值為true.這里的繼承可以不是直接繼承,如果o所繼承的對象繼承自另一個對象,后一個對象繼承自c.prototype,這個表達(dá)式的運算結(jié)果也是true,
???? 2.構(gòu)造函數(shù)是類的公共標(biāo)識,但原型是唯一的標(biāo)識。盡管Instanceof運算符的右操作數(shù)是構(gòu)造函數(shù),但計算過程實際上是檢測了對象的繼承關(guān)系,而不是檢測創(chuàng)建對象的構(gòu)造函數(shù)。
???? 3.isPrototypeOf()方法:不使用構(gòu)造函數(shù)作為中介,來檢查對象的原型鏈上是否存在某個特定的原型對象。
??????? range.methods.isPrototypeOf(r); //range.method 是原型對象
???? 4.instancof運算符和isProtootypeOf()方法的缺點是:
???????? 我們無法通過對象來獲得類名,只能檢測對象是否屬于指定的類名。
???????? 在客戶端JS中還有一個比較嚴(yán)重的不足,就是在多窗口和多框架子頁面的Web應(yīng)用中兼容性不佳。每個窗口和框架子頁面都具有單獨的執(zhí)行上下文,每個上下文都包含獨有的全局變量和一組構(gòu)造函數(shù)。在兩個不同框架頁面中創(chuàng)建的兩個數(shù)組繼承自兩個相同但相互獨立的原型對象,其中一個框架頁面中的數(shù)組不是另一個框架頁面的Array()構(gòu)造函數(shù)的實例,instanceof運算結(jié)果是false。
二.constructor屬性
???? 1.另一種識別對象是否屬于某個類的方法是使用constructor屬性,因為構(gòu)造函數(shù)是類的公共標(biāo)識,所以最直接的方法就是使用constructor屬性,比如:
???????? function typeAndValue(x){
??????????? if(x == null ) return ""; //Null和undefined沒有構(gòu)造函數(shù)
??????????? switch(x.constructor){
????????????? case Number : return "Number" + x; //處理原始類型
????????????? case String : return "String: ' " + x + " ' ";
????????????? case Date : return "Date" + x; //處理內(nèi)置類型
????????????? case RegExp : return "RegExp:" + x;
????????????? case Complex : return "Complex:" + x; //處理自定義類型
??????????????? }
?????????? }
???? 需要注意的是,在代碼中關(guān)鍵字case后的表達(dá)式都是函數(shù),如果改用typeof運算符或獲取到對象的class屬性的話,它們應(yīng)當(dāng)改為字符串。
???? 2.使用constructor屬性檢測對象屬于某個類的技術(shù)的不足之處和instanceof一樣。在多個執(zhí)行上下文的場景中它是無法正常工作的(比如在瀏覽器窗口的多個框架子頁面中)。在這種情況下,每個框架頁面各自擁有獨立的構(gòu)造函數(shù)集合,一個框架頁面中的Array構(gòu)造函數(shù)和另一個框架頁面的Array構(gòu)造函數(shù)不是同一個構(gòu)造函數(shù)。
??????? 同樣,在javascript中也并非所有的對象都包含constructor屬性。在每個新創(chuàng)建的函數(shù)原型上默認(rèn)會有constructor屬性,但我們常常會忽覺原型上constructor屬性。比如例9-1和例9-2它們的實例都沒有constructor屬性。
三.構(gòu)造函數(shù)的名稱
? ? 1.使用instanceof運算符和constructor屬性來檢測對象所屬的類有一個主要的問題,在多個執(zhí)行上下文中存在構(gòu)造函數(shù)的多個副本的時候,這兩種方法的檢測結(jié)果會出錯。多個執(zhí)行上下文中的函數(shù)看起來是一模一樣,但它們是相互獨立的對象,因此彼此也不相等。
? ? 2.一種可能的解決方案是使用構(gòu)造函數(shù)的名字而不是使用構(gòu)造函數(shù)本身作為類標(biāo)識符。
?????? 一個窗口里的Array構(gòu)造函數(shù)和另一個窗口的Array構(gòu)造函數(shù)是不相等的,但是它們的名字是一樣的。
?????? 在一些js的實現(xiàn)中為函數(shù)對象提供了一個非標(biāo)準(zhǔn)的屬性name,用來表示函數(shù)的名稱。
?????? 對于那些沒有name屬性的javascript實現(xiàn)來說,可以將函數(shù)轉(zhuǎn)換為字符串,然后從中提取出函數(shù)名。?
??? 3.例9-4:可以判斷值的類型的typeof()函數(shù)?
?????? /*以字符串形式返回o的類型:如果o是null,返回"null";如果o是NaN,返回"nan"。。。如果typeof所返回的值不是"object",則返回這個值。。如果o的類不是"object",則返回這個值,,如果o包含構(gòu)造函數(shù)并且這個構(gòu)造函數(shù)具有名稱,則返回這個名稱,,,否則,一律返回"object"。*/
??????? function type (o){
?????????? var t,c,n;? //type,class,name
?????????? //處理null值的特殊情況
?????????? if(o===null)return "null";
?????????? //另外一種特殊情況:NaN和它自身不相等
????????? if(o!==o) return "nan";
?????????? //如果typeof的值不是"object",則使用這個值,這可以識別出原始值得類型和函數(shù)
?????????? if((t == typeof o)!=="object") return t;
????????? //返回對象的類名,除非值為"object",這種方式可以識別出大多數(shù)的內(nèi)置對象。
????????? if((c == classof(o))!=="Object") return c;
???????? //如果對象構(gòu)造函數(shù)的名字存在的話,則返回它
????????? if(o.constructor && typeof o.constructor === "function" && (n = o.constructor.getName())) return n;
????????? //其他的類型都無法判別,一律返回"Object"
????????? return "Object";
???????? }
??????? //返回對象的類
??????? function classof(o){
????????? return Object.prototype.toString.call(o).slice(8,-1);
???????? };
??????? //返回函數(shù)的名字(可能是空字符串),不是函數(shù)的話返回null
???????? Function.prototype.getName = function(){
??????????? if("name" in this) return this.name;
??????????? return this.name = this.toString().match(/function\s*([^(]*)\(/)[1])
????????? };
???????? var a = new Date();//Date
?? ??? ? var b = [1,2,3]; //Array
?? ??? ? var c = {}; //Object
?? ??? ? var d = true; //boolean
?? ??? ? var e = "1"; //string
?? ??? ? var f = 1;//number
?? ??? ? var g = function(){};//function
?? ??? ? var h = new Function(); //function
???????? console.log(type(g));
???????? 這種使用構(gòu)造函數(shù)名字來識別對象的類的做法和使用constructor屬性一樣有一個問題:并不是所有的對象都具有constructor屬性。此外,并不是所有的函數(shù)都有名字。如果使用不帶名字的函數(shù)定義表達(dá)式定義一個構(gòu)造函數(shù),getName()方法則會返回空字符串:
???????? //這個構(gòu)造函數(shù)沒有名字
???????? var Complex = function(x,y){ this.r = x;this.i=y; }
???????? //這個構(gòu)造函數(shù)有名字
???????? var Range = function Range(f,t){ this.from = f;this.to = t; }
轉(zhuǎn)載于:https://www.cnblogs.com/hanxuming/p/5849476.html
總結(jié)
以上是生活随笔為你收集整理的《JS权威指南学习总结--9.5 类和类型》的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ubuntu 16.04 桌面菜单栏 任
- 下一篇: 08-SSH综合案例:前台用户模块:注册