JavaScript 有Date、Array、String等這樣的內建物件,功能強大使用簡單,人見人愛,但在處理一些複雜的邏輯的時候,內建物件就很無力了,往往需要開發者自定義物件。
物件是什麼
從JavaScript定義上講物件是無序屬性的集合,其屬性可以包含基本值、物件或函式。也就是說物件是一組沒有特定順序的屬性,每個屬性會對映到一個值上,是一組鍵值對,值可以是資料或物件。
最簡單的物件
JavaScript的一對花括號{}就可以定義一個物件,這樣的寫法實際上和呼叫Object的建構函式一樣
var obj={}; var obj2=new Object();
這樣構建出來的物件僅僅包含一個指向Object的prototype的指標,可以使用一些valueOf、hasQwnProperty等方法,沒有多大實際作用,自定義物件嘛總要有一些自定義的屬性、方法神馬的。
var obj={}; obj.a=0; obj.fn=function(){ alert(this); } var obj2={ a:0, fn:function(){ alert(this); } }
可以在定義完物件後通過”.”為其新增屬性和方法,也可以使用字面量賦值方法在定義物件的時候為其新增屬性和方法,這樣建立的物件,其方法和屬性可以直接使用物件引用,類似於類的靜態變數和靜態函式,這樣建立物件有一個明顯缺陷——在定義大量物件的時候很費力,要一遍遍的寫幾乎是重複的程式碼。
抽象一下
既然是重複程式碼就可以抽象出來,用函式來做這些重複工作,在建立物件的時候呼叫一個專門建立物件的方法,對於不同的屬性值只需要傳入不同引數即可。
function createObj(a,fn){ var obj={}; obj.a=a; obj.fn=fn; return obj; } var obj=createObj(2,function(){ alert(this.a); });
這樣在建立大量物件的時候,就可以通過呼叫此方法來做一些重複工作了,這種方式也不完美,因為在很多時候需要判斷物件的型別,上面程式碼建立出來的物件都是最原始的Object物件例項,只是擴充了一些屬性和方法。
有型一些
又是function登場的時候,JavaScript中function就是個物件,在建立物件的時候打可以拋開上面createObj方法,直接使用function作為物件,怎麼實現複用呢,這就在於function作為物件的特殊性了。
1. function可以接受引數,可以根據引數來建立相同型別不同值的物件
2. function作為建構函式(通過new操作符呼叫)的時候會返回一個物件,在貧下中農版jQuery中提到過一些建構函式的基本知識,簡單複製一下
建構函式的返回值分為兩種情況,當function沒有return語句或者return回一個基本型別(bool,int,string,undefined,null)的時候,返回new 建立的一個匿名物件,該物件即為函式例項;如果function體內return一個引用型別物件(Array,Function,Object等)時,該物件會覆蓋new建立的匿名物件作為返回值。
3. 那麼使用function怎麼解決型別識別問題呢,每個function例項物件都會有一個constructor屬性(也不是“有”,而是可以對應),這個屬性就可以指示其構造是誰,也可以使用instanceof 操作符來做判斷物件是否為XXX的例項。
不能光說不練,上程式碼
function Person(name){ this.name=name; this.fn=function(){ alert(this.name); } } var person1=new Person('Byron'); console.log(person1.constructor==Person);//true console.log(person1 instanceof Person); //true
這樣就完美了吧,也不是!雖然建構函式可以是物件有型,但物件的每個例項中的方法都要重複一遍!
function Person(name){ this.name=name; this.fn=function(){ alert(this.name); } } var person1=new Person('Byron'); var person2=new Person('Frank'); console.log(person1.fn==person2.fn);//false
看看看,雖然兩個例項的fn一模一樣,但是卻不是一回事兒,這如果一個function物件有一千個方法,那麼它的每個例項都要包含這些方法的copy,很讓記憶體無語啊。
不玩兒虛的了
究竟有沒有一種近乎完美的構造物件的方式,及不用做重複工作,又有型,物件通用方法又不必重複?其實可以發現使用function已經距離要求和接近了,只差那麼一點兒——需要一個所有function物件的例項共享的容器,在這個容器記憶體發例項需要共享的屬性和方法,正好這個容器是現成的——prototype,不瞭解prototype的同學可以看看JavaScript prototype
function Person(name){ this.name=name; } Person.prototype.share=[]; Person.prototype.printName=function(){ alert(this.name); } var person1=new Person('Byron'); var person2=new Person('Frank'); console.log(person1.printName==person2.printName);//true
這樣每個Person的例項都有自己的屬性name,又有所有例項共享的屬性share和方法printName,基本問題都解決了,對於一般的物件處理就可以始終這個有型又有愛的建立物件模式了。