JavaScript 的繼承機制(圖文)

jopen 10年前發布 | 12K 次閱讀 JavaScript開發 JavaScript

一、JavaScript的一些語言特性

          1.當我們聲明一個函數時,實際上是定義了一個函數類型的對象。如下所示,下面三種方式定義函數對象結果是一樣的。

 var  func = function(){
 //....define code goes there.
}

function func ()
{
  // ...define code goes there.
}

var func  = new Function(....);

          而當我們使用它時,它會一次執行其內的代碼。

          2. this 指針的作用。在函數的內部,函數的this指針的作用域是動態綁定的,即this 代表的作用域是 上面的func 變量的作用域。但是,當我們使用new func()時,此時會為函數 func 獨立出一塊內存區域,this 的作用域便是func自己的區域。

 var func = function()
{
   this.name = "louis";
  this.age  = 22;
}
func(); //此時函數運行后,在外部window 對象可以訪問name,age

var a = new func();// 此時的函數運行后,a.name,b,name.

           總結:出現上面的情況是因為函數 是一個function 類型的對象,其中,內部定義的執行語句是不可識別的,都是以字符串的形式存儲在相應的區域,當我們調用它們的時候,即使用() 的時候,這時候的代碼才會被拿出來,在給定的一個作用域內解析并且執行。這就是所謂的動態綁定: 即只有在運行的情況下才知道其執行的上下文。

           3.根據上面的函數的特性,我們現在定義了一個Person類 ,和一個Woman 類,由Woman類要繼承Person類,我們可以在Woman內,創建一個對Person 變量的一個引用,然后執行之,這時候函數執行的上下文是Woman內部,即Person函數執行后,Person 內部的變量、屬性自然隸屬于 Woman 創建的對象了.

function Person()
{
        this.name="people";
       this.speak = function(){
              console.log("hello,Fellow");
       }      
}
// Woman要繼承Person類

function Woman()
{

     this.birthe = function(){
                console.log("brithing...");
     }
}

這種繼承的方式,叫做 對象冒充。

 function Woman()
{
      //對象冒充方式,將函數Person動態在Woman內部執行
      this.newMethod = Person;
      this.newMethod();
      delete this.newMethod;

      this.birthe = function(){
                      console.log("birthing....");
      }     

}

二、繼承的方式介紹

             1. 對象冒充(如上所述)

             d1.png

            對象冒充可以實現多重繼承:

 function ClassZ() {
    this.newMethod = ClassX;
    this.newMethod();
    delete this.newMethod;

    this.newMethod = ClassY;
    this.newMethod();
    delete this.newMethod;
}

      上面的模式有個弊端,就是ClassX和ClassY 的屬性定義中,如果有重復的情況,則對于繼承者ClassZ而言,要看其繼承順序,后面的聲明繼承的類會覆蓋先聲明的類,即:ClassY的屬性和 ClassX重合的話,ClassY會覆蓋ClassX內的屬性。

        以對象冒充為原理,JavaScript提供了兩個可以完成此繼承的的方法:apply(),call();

         假設現在有對象a, 它要繼承 B中的屬性和方法,如下所示:

 function B (words)
{
      this.name="hello";
      this.say= function(){
       console.log(words);
};

}
var a = new Object();
//a 繼承B內的屬性。
B.call(a,"hello");
B.apply(a,new Array("hello"));

   2. 原型模式

       在我們現實生活中,經常聽到 某某東西出現了山寨貨,那所謂的山寨貨,則是以某個正品貨為原型造出來的東西,即是仿的。javascript 內的“原型”,和這個意思差不多,都是以某一對象作為參考,進行對象的創建。故而,我們在對象的創建時,如果需要以某一對象作為原型,則如下操作:

 // 設定B 以A 為原型創建
function  A()
{
      this.attr1;
      this.attr2;
      this.method1();
     ///....
}
function B()
{
}
B.prototype = new A();

var b = new B();// 繼承A內所有的屬性

      另外A 也可以以其它對象作為原型進行創建對象,由此,便組成了原型鏈:

d2.png

    使用原型繼承機制的一個弊端,就是B.prototype = new A(); A () 是不可以帶參數的。如果使用參數,則可以使用對象冒充。

 function ClassA(sColor) {
    this.color = sColor;
}

ClassA.prototype.sayColor = function () {
    alert(this.color);
};

function ClassB(sColor, sName) {
    ClassA.call(this, sColor);
    this.name = sName;
}

ClassB.prototype = new ClassA();

ClassB.prototype.sayName = function () {
    alert(this.name);
};

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!