javascript面向?qū)ο蟪绦蛟O(shè)計(一)
更新時間:2015年01月29日 09:36:16 投稿:hebedich
這篇文章主要介紹了javascript面向?qū)ο蟪绦蛟O(shè)計,分享給大家一段代碼,注釋里講解的非常詳細,有助于我們理解面向?qū)ο?,這里推薦給大家。
注釋里講解的十分細致了,這里就不多廢話了,直接上代碼:
<script type="text/javascript"> //ECMA-262把對象定義為:“無序?qū)傩缘?集合,其屬性可以包含基本值、對象或者函數(shù)” //理解對象,最簡單的方式就是通過創(chuàng)建一個Object的實例,然后為它添加屬性和方法 var person = new Object(); person.name = "Xulei"; person.age = "23"; person.job = "前端工程師"; person.sayName = function () { alert(this.name); } //還可以這樣寫 var person = { name: "xulei", age: 23, job: "前端工程", sayName: function () { alert(this.name) } } //一、屬性類型:數(shù)據(jù)屬性和訪問其屬性 //1、數(shù)據(jù)屬性,有4個描述其行為的特性 //[Configurable]:表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性,默認值為true //[Enumerable]:表示能否通過for-in返回屬性,默認值為true //[Writable]:表示能否修改屬性,默認值為true //[Value]:包含這個屬性的數(shù)據(jù)值。默認值為undefined var person = { name: "xulei" } //這里創(chuàng)建了一個person對象,value值就是“xulei” //要修改屬性的默認特性,必須使用ECMAScript5的Object.defineProperty(屬性所在的對象,屬性的名字,描述符對象) //描述符對象必須是configurable、enumerable、writable、value var peron = {} Object.defineProperty(peron, "name", { writable: false,//屬性不能被修改 value: "徐磊-xulei" }); alert(peron.name);//徐磊-xulei peron.name = "徐磊"; alert(peron.name);//徐磊-xulei //以上操作在非嚴格模式下賦值操作會被忽略,如果在嚴格模式下會拋出異常 //一旦把屬性定義為不可配置的就不能把它變回可配置的了。 //在多數(shù)情況下都沒有必要利用Object.defineProperty()方法提供的這些高級功能。但是對理解javascript非常有用。 //建議讀者不要在ie8上使用此方法。 //2、訪問其屬性,有4個特性 //[Configurable]:表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性,默認值為true //[Enumerable]:表示能否通過for-in返回屬性,默認值為true //[Get]:在讀取時調(diào)用的函數(shù) 默認值undefined //[Set]:在寫入屬性時調(diào)用的函數(shù) 默認值Undefined var book={ _year:2004, edition:1 } Object.defineProperty(book,"year",{ get:function(){ return this._year; }, set:function(value){ if(value>2004){ this._year=value; this.edition +=value-2004; } } }); book.year=2005; alert(book.edition);//2 //創(chuàng)建對象 //1、將構(gòu)造函數(shù)當做函數(shù) function Person(name,age,job) { this.name=name; this.age=age; this.job=job; this.sayName=function(){ alert(this.name); } } //當做構(gòu)造函數(shù)使用 var person=new Person("xulei",23,"software"); person.sayName(); //作為普通函數(shù)使用 Person("xulei2",23,"job2");//添加到window中 window.sayName(); //在另一個對象的作用域中調(diào)用 var o=new Object(); Person.call(o,"xulei3",23,"job3"); o.sayName(); </script>
再來一段:
<script type="text/javascript"> //1、理解原型對象 //2、原型與in操作符 //3、更簡單的原型語法 //4、原型的動態(tài)性 //5、原生對象原型 //6、原型對象的問題 //1、無論什么時候,只要創(chuàng)建了一個函數(shù),就會根據(jù)一組特定的規(guī)則,為該函數(shù)創(chuàng)建一個prototype屬性,該屬性指向函數(shù)的原型對象 //在默認情況下,所有的原型對象都會自動獲得一個constructor(構(gòu)造函數(shù))屬性,這個屬性包含一個指向prototype屬性所在函數(shù)的指針 //如 function Person(){ } //Person.prototype.constructor 指向Person //創(chuàng)建了自定義的構(gòu)造函數(shù)之后,其原型對象默認只會取得constructor屬性,至于其他方法則都是從Object繼承而來 //當調(diào)用函數(shù)的創(chuàng)建一個新實例之后,該實例的內(nèi)部包含一個指針(內(nèi)部屬性)指向構(gòu)造函數(shù)的原型對象 //在Firefox、safari、chrome在每個對象上都支持一個屬性_proto_訪問 var p1=new Person(); alert(Person.prototype.isPrototypeOf(p1)) alert(Object.getPrototypeOf(p1)==Person.prototype) //雖然可以通過對象實例訪問保存在原型中的值,但卻不能通過對象實例重寫原型中的值。如果我們在實例中添加了一個屬性 //而該屬性的名稱與原型的中的實例同名,那我們就在實例中創(chuàng)建該屬性,該屬性將會屏蔽原型中的那個屬性。eg: function Person() { } Person.prototype.name="amber"; Person.prototype.age=23; Person.prototype.job="software engineer"; Person.prototype.sayName=function(){ alert(this.name) } var person1=new Person(); var person2=new Person(); person1.name="amber.Xu"; alert(person1.name);//amber.xu --來自實例 alert(person2.name);//amber --來自原型 delete person1.name; alert(person1.name);//amber --來自原型 //使用hasOwnProperty()方法可以檢測一個屬性是存在于實例中還是存在于原型中,這個方法(從Object繼承而來) //只在給定屬性存在于對象實例中時,才會返回true function Person() { } Person.prototype.name="amber"; Person.prototype.age=23; Person.prototype.job="software engineer"; Person.prototype.sayName=function(){ alert(this.name) } var person1=new Person(); var person2=new Person(); alert(person1.hasOwnProperty("name"));//false 來自實例 alert(person2.hasOwnProperty("name"));//false 來自實例 person1.name="amber.xu"; alert(person1.name); alert(person1.hasOwnProperty("name"));//true 來自實例 delete person1.name; alert(person1.name); alert(person1.hasOwnProperty("name"));//false 來自原型 //2、原型與in操作符 //in 有兩種使用方式,一個是的單獨使用和在for-in 中使用。在單獨使用時,in操作符會在對象能夠訪問給定屬性時返回true //無論該屬性時來自原型還是實例 function Person() { } Person.prototype.name="amber"; Person.prototype.age=23; Person.prototype.job="software engineer"; Person.prototype.sayName=function(){ alert(this.name) } var person1=new Person(); var person2=new Person(); alert("name" in person1);//true 來自原型 alert("name" in person2);//true 來自原型 alert("height" in person1);//false //這樣就可以封裝一個函數(shù)(給定屬性是否是來給定對象的原型) function hasPrototypeProperty(object,name){ return !object.hasOwnProperty(name) && (name in object); } alert("----------------------------------"); alert(hasPrototypeProperty(person1,"name"));//true person1.name="張三"; alert(hasPrototypeProperty(person1,"name"));//false //使用for-in 返回的是所有能夠通過對象訪問、可枚舉的屬性,其中既包含原型屬性也包含實例屬性。 //屏蔽了原型中不可枚舉屬性(將Enumerable標記為false的屬性)的實例屬性也會在for-in中返回 //ie早期版本總中有一個bug:屏蔽了原型中不可枚舉屬性的實例屬性也不會在for-in中返回 //eg: var o={ toString:function(){ return "my object"; } }; for(var prop in o){ if(prop=="toString"){ alert("找到了");//在ie早期版本中不會顯示 } } //要取得對象上所有可枚舉的屬性,可以使用ECMAScript5的Object.keys()方法。接受一個對象作為參數(shù), //包含所有可枚舉屬性的字符串數(shù)組 function Person() { } Person.prototype.name="amber"; Person.prototype.age=23; Person.prototype.job="software engineer"; Person.prototype.sayName=function(){ alert(this.name) } var person1=new Person(); var person2=new Person(); var keys=Object.keys(Person.prototype); alert(keys) person1.name="amber.Xu"; person1.age=23; var keys=Object.keys(person1); alert(keys) alert("-----------------------------------------") //如果想要得到所有的實例屬性不管他是否可以枚舉,都可以使用 alert(Object.getOwnPropertyNames(person1)); alert(Object.getOwnPropertyNames(Person.prototype)); alert("更簡單的原型語法-----------------------------------------") //3、更簡單的原型語法 function Person() { } Person.prototype={ name:"AMBER", age:23, job:"software", sayName:function(){ alert(this.name) } } //這樣寫之后constructor屬性不再指向Person函數(shù),而是指向Object構(gòu)造函數(shù)。 //盡管通過instanceof操作符還能返回正確的結(jié)果,但是通過constructor已經(jīng)無法確定對象的類型了,eg: var friend=new Person(); alert(friend instanceof Person)//true alert(friend instanceof Object)//true alert(friend.constructor==Person);//false alert(friend.constructor==Object);//true //如果constructor對你真的很重要,可以向下面一樣設(shè)置成適當?shù)闹? function Person() { } Person.prototype={ constructor:Person, name:"AMBER", age:23, job:"software", sayName:function(){ alert(this.name) } } var friend=new Person(); alert("手動設(shè)置constructor-----------------------------------------") alert(friend.constructor==Person);//true //這種手動的添加了constructor會使constructor變成可枚舉的元(原生的constructor屬性時不可枚舉的)。 //這種情況下就可以使用 Object.defineProperty(Person.prototype,"constructor",{ enumerable:false, value:Person }); //原型的動態(tài)性 var friend=new Person(); Person.prototype.sayHi=function(){ alert("Hi"); } friend.sayHi();//Hi (正常執(zhí)行) //因為實例和原型之間是松散的連接關(guān)系,實例與原型之間的連接只不過是一個指針,而非副本 //當我們調(diào)用sayHi()方法時,首先會在實例中搜索名為sayHi的方法,在沒找到的情況下會搜索原型。 //但是,如果是重寫整個原型對象,那么情況就不一樣了。 //我們知道,調(diào)用構(gòu)造函數(shù)時會為實例添加一個指向最初原型的Prototype指針,而把原型修改為另一個對象就等于切斷了構(gòu)造函數(shù)與最初原型之間的聯(lián)系。 //請記?。簩嵗械闹羔槂H指向原型,而不指向構(gòu)造函數(shù)。eg: function A(){} var a1=new A(); A.prototype={ constructor:A, name:"AMBER", age:23, job:"software", sayName:function(){ alert(this.name) } } alert("ERROR-------------------------------------"); alert(a1.sayName()); //我們創(chuàng)建了一個A的實例,然后又重寫了其原型對象,然后在調(diào)用a1.sayName()發(fā)生了錯誤,因為a指向的原型中不包含以該名字命名的屬性/方法 //原生對象的原型 //原型模式的重要性不僅體現(xiàn)在創(chuàng)建自定義類型方面。就連所有的原生的引用類型,都是采用這種模式創(chuàng)建的。所有的原生引用類型 //都在其構(gòu)造函數(shù)的原型上定義的方法 eg: alert(typeof Array.prototype.sort);//function alert(typeof String.prototype.substring);//function //不僅可以在原生對象的原型取得雖有默認方法的引用,而且可以定義新的方法 //為String類型添加一個startsWith()的方法 String.prototype.startsWith=function(text){ return this.indexOf(text) == 0; }; var msg="Hello"; alert(msg.startsWith("H")); //我們并不建議這樣做。 alert("原型對象的問題"); //6、原型對象的問題 實例 function Ques() { } Ques.prototype={ constructor:Ques, name:"amber", age:23, job:"IT", friends:["張三","李四"],//引用類型 sayName:function(){ alert(this.name) } }; var q1=new Ques(); var q2=new Ques(); q1.friends.push("王五"); alert(q1.friends);// alert(q2.friends);// alert(q1.friends===q2.friends); //相信大家已經(jīng)看到了問題,當我創(chuàng)建了兩個實例q1、q2,當我為q1的“朋友”添加了“王五”之后,q2的”朋友“也有了三個張三、李四、王五 //那是因為數(shù)組存在于Ques.prototype上,而非q1上。所以出現(xiàn)了如上結(jié)果。 //而正是這個問題,我們很少看到有人單獨使用原型模式的原因所在。 </script>
本文就先到這里了,后續(xù)我們再繼續(xù)討論javascript面向?qū)ο蟪绦蛟O(shè)計,希望大家能夠喜歡。
相關(guān)文章
js拆分字符串并將分割的數(shù)據(jù)放到數(shù)組中的方法
這篇文章主要介紹了js拆分字符串并將分割的數(shù)據(jù)放到數(shù)組中的方法,涉及javascript中split方法及數(shù)組的操作技巧,需要的朋友可以參考下2015-05-05javascript實現(xiàn)檢驗的各種規(guī)則
這篇文章主要介紹了javascript實現(xiàn)檢驗的各種規(guī)則,涉及javascript針對手機號、郵箱、網(wǎng)址、漢字及圖片等相關(guān)檢測技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-07-07