物件之間繼承的 5 中方法.
比如, 現在有乙個"動物"物件的建構函式.
function animal()
還有乙個"貓"物件建構函式
function cat(name,color)
怎樣才能使貓繼承動物呢?
一.建構函式繫結
function cat(name,color)
var cat1 = new cat("大毛","黃色");
alert(cat1.species);//貓科動物
1doctype html
>
2<
html
>
3<
head
>
4<
meta
charset
="utf-8"
>
5<
title
>0.2-1 obj
title
>
6head
>
7<
body
>
8<
script
>9//
父建構函式
10function
animal()
1314
//子建構函式
15function
cat(name,color)
2021
//構造例項
22var
cat1
=new
cat("大毛
","黑色
");23alert(cat1.species);
24script
>
25body
>
26html
>
二.prototype模式
第二種方法更常見,使用 prototype屬性.
如果用"貓"的prototype物件,指向乙個animal的例項,那麼所有"貓"的例項,就能繼承animal了.
cat.prototype = new animal();
它相當於完全刪除了prototype物件原先的值, 然後賦予乙個新值.但是第二行又是什麼意思呢?
cat.prototype.constructor = cat;
原來, 任何乙個prototype物件都有乙個constructor屬性,指向它的建構函式.如果沒有"cat.prototype=new animal();"這一行,cat.prototype.constructor是指向cat的;加了這一行以後,cat.prototype.constructor指向animal.
alert(cat.prototype.constructor == animal);//true
cat1使用建構函式cat生成的,因此我們需要手動糾正,將cat.prototype物件的contructor值改為cat,不然就會導致繼承鏈的紊亂.
注: 這是程式設計中很重要的一點,程式設計時務必遵守.
如果替換了prototype物件,
o.prototype = {};
那麼, 下一步必然會成為新的 prototype物件加上constructor屬性,並將這個屬性指回原來的建構函式.
o.prototype.constructor = o;
1doctype html
>
2<
html
>
3<
head
>
4<
meta
charset
="utf-8"
>
5<
title
>0.2-2
title
>
6head
>
7<
body
>
8<
script
>
9function
animal()
1213
function
cat(name,color)
17cat.prototype
=new
animal();
18alert(cat.prototype.constructor);
//animal
19cat.prototype.constructor
=cat;
20alert(cat.prototype.constructor);
//cat
2122
varcat1
=new
cat("大毛
","黃色
");23alert(cat1.species);
//動物
2425
script
>
26body
>
27html
>
三.直接繼承prototype
第三種方法是對第二種方法的改進. 由於animal物件中, 不變的屬性都可以直接寫入 animal.prototype. 所以,我們也可以讓 cat()跳過aniaml(),直接繼承animal.prototype.
現在, 我們先將animal物件改寫:
function animal(){}
animal.prototype.species = "動物";
然後,將 cat的prototype物件,然後指向animal的prototype物件,這樣就完成了繼承.
cat.prototype = animal.prototype;
cat.prototype.constructor = cat;
var cat1 = new cat("大毛","黃色");
alert(cat1.species);//動物
與前一種方法相比, 這樣做的優點是效率比較高(不用執行和建立animal的例項了),比較省記憶體. 缺點是cat.prototype和animal.prototype現在指向了同乙個物件,那麼任何對cat.prototype的修改,都會反映到animal.prototype.
所以,上面這一段**其實是有問題的.請看第二行
cat.prototype.constructor = cat;
這一句話實際上把aniaml.prototype物件的constructor屬性也改掉了!
alert(animal.prototype.constructor);//cat
四.利用空物件作為中介
由於"直接繼承prototype"存在上述的缺點,所以就有第四種方法,利用乙個空物件作為中介.
var f = function(){};
f.prototype = animal.prototype;
cat.prototype = new f();
cat.prototype.constructor = cat;
f是空物件,所以幾乎不佔記憶體.這時,修改cat的prototype物件,就不會影響到animal的prototype物件.
alert(animal.prototype.constructor);//animal
我們將上邊的方法,封裝成乙個函式,便於使用.
function extend(child,parent);
f.prototype = parent.prototype;
child.prototype = new f();
child.prototype.constructor = child;
child.uber = parent.prototype;
}//使用方法如下:
extend(cat,animal);
var cat1 = new cat("大毛","黃色");
alert(cat1.species);//動物
這個extend函式,就是yui庫如何實現繼承的方法.
另外,說明一點,函式體最後一行
child.uber = parent.prototype;
意思是為子物件設乙個uber屬性, 這個屬性直接指向父物件的prototype屬性.這等於在子物件上開啟一條通道,可以直接呼叫父物件的方法.這一行放在這裡,只是為了實現繼承的完備性,純屬備用性質.
五.拷貝繼承
上面採用prototype物件,實現繼承.我們也可以換一種思路,純粹採用"拷貝"方法實現繼承.簡單說,如果把父物件的所有屬性和方法,拷貝進子物件,不也能夠實現繼承嗎?
首先,還是把animal的所有不變屬性, 都放到它的prototype物件上.
function animal(){};
animal.prototype.species = "動物";
然後,再寫乙個函式,實現屬性拷貝的目的.
function extend2(child, parent)
c.uber = p;
}這個函式的作用,就是將父物件的prototype物件中的屬性,一一拷貝給child物件的prototype物件.
使用的時候,這樣寫:
extent2(cat,animal);
var cat1 = new cat("大毛","黃色");
alert(cat1.species);//動物
js物件導向程式設計之建構函式
工廠模式是乙個比較廣為人知的模式,這種模式將細節抽象出來。如下 function createperson name,age,job returno var person1 createperson ds 12,dada var person2 createperson ds2 122,dada2 ...
js 物件導向 建構函式
面向過程的時候我們寫 的方式是獲取元素 定義訊號量 定義鎖都是遇見需求就定義乙個變數 但是 無法復用 並且主要就是定義的 是變數 物件導向就是操作的是物件 把寫 的風格從面向過程改為物件導向 把變數封裝成物件即可 面向過程 var username 王老五 var age 13 var 男 cons...
C 物件導向程式設計《二》 建構函式
class complex 類的前置宣告只是告訴將類的名稱編譯器,並未提供class的任何其他資訊,因此前置宣告使我們得以使用類的指標和引用,而不能使用類的物件,如下 complex p 0 定義乙個類指標 class pointer void func const complex 以complex...