javascript的prototype繼承

來源:互聯網
上載者:User
基本的用法 把ClassA的一個執行個體賦值給ClassB ClassB就繼承了ClassA的所有屬性

<script>
function ClassA()
{
    this.a='a';
}
function ClassB()
{
    this.b='b';
}
ClassB.prototype=new ClassA();
var objB=new ClassB();
for(var p in objB)document.write(p+"<br>");
</script>

從原型繼承理論的角度去考慮 js的原型繼承是引用原型 不是複製原型
所以 修改原型會導致所有B的執行個體的變化

<script>
function ClassA()
{
    this.a='a';
}
function ClassB()
{
    this.b='b';
}
ClassB.prototype=new ClassA();
var objB=new ClassB();
alert(objB.a);
ClassB.prototype.a='changed!!';
alert(objB.a);
</script>

然而 子類對象的寫操作只訪問子類對象中成員 它們之間不會互相影響
因此 寫是寫子類 讀是讀原型(如果子類中沒有的話)

<script>
function ClassA()
{
    this.a='a';
}
function ClassB()
{
    this.b='b';
}
ClassB.prototype=new ClassA();
var objB1=new ClassB();
var objB2=new ClassB();
objB1.a='!!!';
alert(objB1.a);
alert(objB2.a);
</script>

每個子類對象都執有同一個原型的引用 所以子類對象中的原型成員實際是同一個

<script>
function ClassA()
{
    this.a=function(){alert();};
}
function ClassB()
{
    this.b=function(){alert();};
}
ClassB.prototype=new ClassA();
var objB1=new ClassB();
var objB2=new ClassB();
alert(objB1.a==objB2.a);
alert(objB1.b==objB2.b);
</script>

構造子類時 原型的建構函式不會被執行<script>
function ClassA()
{
    alert("a");
    this.a=function(){alert();};
}
function ClassB()
{
    alert("b");
    this.b=function(){alert();};
}
ClassB.prototype=new ClassA();
var objB1=new ClassB();
var objB2=new ClassB();
</script>

接下來是致命的,在子類對象中訪問原型的成員對象:<script>
function ClassA()
{
    this.a=[];
}
function ClassB()
{
    this.b=function(){alert();};
}
ClassB.prototype=new ClassA();
var objB1=new ClassB();
var objB2=new ClassB();
objB1.a.push(1,2,3);
alert(objB2.a);
//所有b的執行個體中的a成員全都變了!!
</script>

所以 在prototype繼承中 原型類中不能有成員對象! 所有成員必須是實值型別資料(string也可以)

用prototype繼承有執行效率高,不會浪費記憶體,為父類動態添置方法後子類中馬上可見等的優點。

我就非常喜歡用prototype繼承。

prototype繼承是通過把子類的原型對象(prototype)設定成父類的一個執行個體來進行繼承的。

只簡單的這樣設定繼承的確如樓主所說,有不少缺點。總的來說有四個缺點:

  缺點一:父類的建構函式不是像JAVA中那樣在給子類進行執行個體化時執行的,而是在設定繼承的時候執行的,並且只執行一次。這往往不是我們希望的,特別是父類的建構函式中有一些特殊操作的情況下。

  缺點二:由於父類的建構函式不是在子類進行執行個體化時執行,在父類的建構函式中設定的成員變數到了子類中就成了所有執行個體對象公有的公開變數。由於JavaScript中繼承只發生在“擷取”屬性的值時,對於屬性的值是String,Number和Boolean這些資料本身不能被修改的類型時沒有什麼影響。但是Array和Object類型就會有問題。
  缺點三:如果父類的建構函式需要參數,我們就沒有辦法了。

  缺點四:子類原本的原型對象被替換了,子類本身的constructor屬性就沒有了。在類的執行個體取它的constructor屬性時,取得的是從父類中繼承的constructor屬性,從而constructor的值是父類而不是子類。

我也曾經為了這四個缺點頭疼過,於是對prototype繼承進行改造。
我試了幾種方法,下面是我覺得最好的一種。我把它寫成Function對象的一個方法,這樣用的時候方便。方法如下://類的繼承-海浪版
Function.prototype.Extends = function (parentClass)
{
  var Bs = new Function();
  Bs.prototype = parentClass.prototype;
  this.prototype = new Bs();
  this.prototype.Super = parentClass;
  this.prototype.constructor = this;
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.