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