建立物件 建構函式,原型模式(一)

2021-08-31 03:58:13 字數 2573 閱讀 7144

在建立單個物件的時候,有兩個基本的方法。使用object建構函式或者使用物件字面量。但假如說我們需要建立許多具有部分相同方法,部分相同屬性的一類物件,那麼這樣乙個乙個去建立這樣一類的物件,效率就十分低下,會堆砌出大量重複的**。

所以開發人員發明了一種函式,用函式來封裝以特定介面建立的物件,例如下面的**:

在宣告並初始化person的值的時候,函式createperson執行,函式執行建立了乙個物件o,函式執行中,根據傳入的引數的不同,物件o的每個屬性的值也不同,最後物件o被返回,又賦值給了person,person具有了物件o的所有屬性和方法;而這些方法和屬性都是在函式createperson內部封裝好的,只需要在每次建立person呼叫就可以了。這種大量建立物件方法,叫做工廠模式。

工廠模式雖然解決了建立多個相似物件的問題,但卻沒有解決物件識別的問題,因為在這裡所有的物件person是由物件o賦值得到的,而o全部都是原生object型別。所以我們的需求就由大量建立相似物件,公升級為建立大量自定義型別的相似物件:

首先,我們要知道在使用object建構函式建立單個物件的時候,var obj=new object(),實際上是將obejct的作用域給了obj,所以obj才可以繼承原生建構函式object()的屬性和方法。所以,我們可以自己定義乙個建構函式,然後給建構函式內部新增它自己屬性和方法:

當我們使用

var person1=new person("孫悟空",18,"齊天大聖");
建立乙個物件的時候,會經歷四個步驟:

①會建立乙個叫做person1的新物件;

②這個新物件會繼承建構函式person的作用域;(所以接下來函式執行的時候,this會指向person1);

③執行建構函式中的**;(將屬性和方法給this)

④返回新的物件;

建構函式有點奇怪的地方就是它沒有return語句? 但是在最後返回乙個新的物件給person1,這是我不太明白的地方,應該是與建構函式person是通過new操作符呼叫的有關。

還有一點需要記住的是,通過建構函式建立的物件中,都存在著乙個屬於person,但是不同的例項。這個例項通過constructor(譯:「建造者」)屬性,指向person。

alert(person1.constructor==person);//true;

並且,由於「繼承」的原因,實際上person1,person2不但是person的例項,而且也是object的例項;這一點可以通過操作符instanceof(譯:例項)來證明(instanceof是操作符,不是屬性,使用的時候需要注意);

alert(person1 instanceof person);//true;

alert(person1 instanceof object);//true;

var o=new object();

person.call(o,"紅孩兒",13,"小屁孩");

o.sayname();

同樣,如上**所示,建構函式也可以被其他物件呼叫,呼叫結束之後,那個物件就有了該建構函式的所有屬性和方法。

建構函式雖然好用,但是同樣也有缺點:

①每建立乙個物件,就要執行一次建構函式;

②如上例所示,person1和person2都有乙個sayname方法,但是這個sayname方法並不是只有乙個。如上所說,每建立乙個物件就要執行一次建構函式,就要分發乙個新的sayname方法給新建立的物件;

所以為了效能,實現相同功能的方法只要存在乙個就可以了,可以做出如下改動:

建構函式執行時,不給每個新建立的物件分發方法了,改為分發乙個指向sayname函式的指標sayname;

但是,儘管這樣之後,所有的新建立的物件都共用了乙個方法sayname。還是有不好的地方,那就是這個方法我們希望只有person的例項可以訪問,可是這個方法在全域性之中,有點不太安全的感覺。而且假如說在js**之中還出現了其他與sayname同名的方法,就會導致所有的例項都出錯。

所以我們就再次對**進行優化,引入原型模式:

通過引入原型物件,我們就可以讓所有例項繼承其建構函式原型物件上的屬性和方法;

原型物件:我們建立的每乙個函式都有乙個原型(prototype)屬性,這個屬性是乙個指標,指向乙個物件,這個物件上面所有的方法和屬性對由這個函式建立的例項都是開放的。

當通過建構函式建立乙個新的物件的時候,這個新的物件會有乙個新的例項,例項中會含有乙個指標,我們稱呼這個指標為[[prototype]],這個指標我們無法訪問,但是在新建立的物件上還存在著另外乙個屬性_proto_,每個例項正是通過_proto_去訪問建構函式的原型物件的:

alert(person1.__proto__==person.prototype);//true
前面我們說到了每個例項上面都自帶乙個constructor屬性,這個屬性都是指向建構函式的。但是其實這個屬性並不是在例項上,而是在原型物件上面,**表示為person.prototype.constructor==person。

由於是在原型物件上面,所以每個例項都可以訪問這個constructor屬性。

5 5 混合模式(建構函式加原型模式)建立物件

一 屬性放在建構函式裡方法放在原型上 建構函式 function person name,age 原型模式 person.prototype.fn function name var p1 newperson mrs陳 23 console.log p1 person p1.fn 卡卡 卡卡 con...

原型模式 建立物件

原型模式 操作 先建立好乙個原型物件,然後通過clone 原型物件來建立新的物件。這就免去了類建立時重複的初始化操作。原型模式適用於大物件的建立。如果每次new 就會消耗很大,原型模式僅需要記憶體拷貝即可。index.php 中 prototype new imooc canvas prototyp...

建立物件之組合使用建構函式和原型模式

建立自定義型別的常見方式,就是組合使用建構函式模式與原型模式。建構函式模式用於定義例項屬性,而原型模式用於定義方法和共享的屬性。結果,每個例項都會有自己的乙份例項屬性的副本,但同時又共享著對方法的引用,大限度地節省了記憶體。另外,這種混成模式還支援向建構函式傳遞參 數 可謂是集兩種模式之長。例如 f...