JavaScript---繼承

  JavaScript---繼承

      JavaScript語言的繼承機制---因爲JavaScript沒有‘類(class)’和‘實例(instance)’的概念,他是靠‘原型鏈(prototype  chain)’模式來實現繼承的html

  要理解JavaScript的繼承機制,首先,要清楚這幾個概念:構造函數,實例對象,prototype,constructor、__proto__  以及他們之間的關係。java

      構造函數:用來初始化新建立的對象的函數是構造函數。(你能夠把構造函數當作是「類」)chrome

      實例對象:經過構造函數的new操做建立的對象是實例對象。能夠用同一個構造函數,構造多個實例對象。瀏覽器

      prototype:每一個函數(固然包括構造函數)都有一個prototype屬性,它是一個對象。咱們稱它爲‘原型對象’  prototype:{...}app

      constructor:每一個對象都有一個constructor屬性,它是一個函數:constructor:fn(){...} 它的做用就是指向該原型對象對應的構造函數。因爲實例對象能夠繼承原型對象的屬性,因此實例對象也擁有constructor屬性,一樣指向原型對象對應的構造函數函數

      __proto__:每一個實例對象都有一個proto屬性,指向建立該實例對象的構造函數的原型對象(能夠理解爲 實例對象---》構造函數的原型對象)this

  熟練使用JavaScript的繼承必需要對這幾個概念爛熟於心。spa

    接下來結合圖示來分析一下。prototype

  

 

    要想清楚的瞭解JavaScript的繼承機制,這些概念是必須爛熟於心的。3d

    

    JavaScript的繼承 ---指的是子類繼承父類的屬性和方法

    JavaScript的繼承特色:1.子類擁有父類全部的屬性和方法(代碼複用);2.子類能夠擴展本身的屬性和方法(更加靈活);3.子類能夠重寫父類的方法

 

    JavaScript的繼承方式

      1.組合繼承

        

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>組合繼承法</title>
    <script>
        function Person(name,age,gender,geyan){
            this.name = name;
            this.age = age;
            this.gender = gender;
            this.geyan = geyan;
        }

        Person.prototype.say = function(){
            console.log(`我叫${this.name},${this.gender},我今年${this.age}歲,個人人生格言是:${this.geyan}`);
        }


        var p1 = new Person('lx',18,'','我姓謝,王菲的哪一個謝');
        var p2 = new Person('lw',45,'','你有困難我幫忙,我住隔壁,我姓王');
        p1.say();
        p2.say();


        function Student(){
            // 借用構造函數法
            // Person.call(this,name,age,gender,geyan)
            Person.apply(this,arguments);
        }


        //原型鏈繼承法
        Student.prototype = new Person();
        var s1 = new Student('小明', 12, '', '姐姐,約嗎');
        s1.say();
        console.log(s1);
    </script>
</head>
<body>
    
</body>
</html>

  chrome顯示以下:

 

  組合繼承主要使用:1.借用構造函數法--使用call方法或apply方法借用父類的屬性,使子類能夠使用。 2.原型鏈繼承法---將父類的實例對象賦給子類的原型對象,這樣,子類的原型對象就繼承到了父類的原型對象裏的方法(子類原型對象---》父類原型對象)

  組合繼承的弊端:1.屢次執行了父類構造函數  在咱們的例子中, 每建立一個子類的實例sn,都要調用一次父類構造函數 ,很麻煩。  2.在原型對象裏生成多餘的屬性  緣由在於原型鏈繼承這一步中,父類的實例對象的屬性也被子類的原型對象繼承了。

  知道他的弊端以後,就能加以改進了:將原型鏈繼承法用新的方法替代,這個新的方法叫作:原生式繼承法。這個方法不會生成多餘的屬性

    來看改進過的代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>組合繼承法</title>
    <script>
        function Person(name,age,gender,geyan){
            this.name = name;
            this.age = age;
            this.gender = gender;
            this.geyan = geyan;
        }

        Person.prototype.say = function(){
            console.log(`我叫${this.name},${this.gender},我今年${this.age}歲,個人人生格言是:${this.geyan}`);
        }


        var p1 = new Person('lx',18,'','我姓謝,王菲的哪一個謝');
        var p2 = new Person('lw',45,'','你有困難我幫忙,我住隔壁,我姓王');
        p1.say();
        p2.say();


        function Student(){
            // 借用構造函數法
            // Person.call(this,name,age,gender,geyan)
            Person.apply(this,arguments);
        }


        //原生式繼承法
        function object(o){
            function F(){}
            F.prototype = o;
            return new F();
        }
        Student.prototype = object(Person.prototype);
        var s1 = new Student('小明',12, '', '姐姐,約麼?');
        s1.say();
        console.log(s1);
    </script>
</head>
<body>
    
</body>
</html>

 

  在chrome中顯示:

   原生式繼承法的精髓在於:直接繼承父類的原型,而不是向原型鏈繼承那樣繼承整個父類。但這樣又帶來了一個新的問題:每次繼承都要寫一長串的代碼。

怎麼偷懶? 好在ES5給咱們拓展了關於原型的繼承方法----子類.prototype = Object.create(父類.prototype);

   再看一下改進的代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>組合繼承法</title>
    <script>
        function Person(name,age,gender,geyan){
            this.name = name;
            this.age = age;
            this.gender = gender;
            this.geyan = geyan;
        }

        Person.prototype.say = function(){
            console.log(`我叫${this.name},${this.gender},我今年${this.age}歲,個人人生格言是:${this.geyan}`);
        }


        var p1 = new Person('lx',18,'','我姓謝,王菲的哪一個謝');
        var p2 = new Person('lw',45,'','你有困難我幫忙,我住隔壁,我姓王');
        p1.say();
        p2.say();


        function Student(){
            // 借用構造函數法
            // Person.call(this,name,age,gender,geyan)
            Person.apply(this,arguments);
        }


        //ES5的原型使繼承法
        Student.prototype = Object.create(Person.prototype);

        var s1 = new Student('小明',12,'','姐姐,約麼?');
        s1.say();
        console.log(s1);
    </script>
</head>
<body>
    
</body>
</html>

  

  在chrome中顯示:

這種原型式繼承法+借用構造函數法的強力組合就是JavaScript繼承方式的第2種方法 叫作寄生繼承。這也是最終推薦的繼承方式。

 

 

 

 

你覺得結束了嗎??

 

 

 

 

 

 

 

    講完了ES5,怎能不講講ES6?  ES6給咱們準備了一個「大禮包」!!

      開頭說到,JavaScript沒有「類」的概念。如今有了(JavaScript一直在成長啊)!!ES6中用關鍵字 class 來定義一個類

  先上代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ES6中的繼承方式</title>
    <script>

        // 類: 使用class定義了一個類 Person
        class Person{

            // 構造函數  全部的屬性都放在constructor函數裏(模仿java)
            constructor(name,age){
                this.name = name;
                this.age = age;
            }

            // 全部的方法寫在函數constructor外 注意:並不須要聲明方法 直接 say(){...}的形式 至關於 Person.prototype.say = function(){...}
            say(){
                console.log('say,say');
            }


            // 靜態方法 只會被子類繼承, 不會被子類的實例繼承
            static sing(){
                console.log(`我叫${this.name},我會唱歌`);
            }
        }

        

        // Person.prototype.say = function(){}

        var p1 = new Person('lx',18);
        p1.say();


        // 靜態方法的調用
        Person.sing();

    //使用extends去繼承父類   class 子類 extends 父類{...}
        class Student extends Person{
            constructor(name,age){
                super(name,age);
            }
        }

        var s1 = new Student('小紅',12);

        Student.sing();

        s1.say()


        console.log(p1,s1)
    </script>
</head>
<body>
    
</body>
</html>

 

  在chrome中顯示:

 

是否是很強大!!!                           考慮到部分瀏覽器還未兼容ES6的標準。因此仍是推薦使用ES5的寄生繼承。

 

JavaScript的繼承機制就暫告一段落了。有問題之後補充                  ----2017-03-21-20:10

相關文章
相關標籤/搜索