javascript的幾種繼承

来源:http://www.cnblogs.com/haoxl/archive/2016/03/06/5248854.html
-Advertisement-
Play Games

1.原型鏈繼承:構造函數、原型和實例的關係:每個構造函數都有一個原型對象,原型對象都包含一個指向構造函數的指針,而實例都包含一個指向原型對象的內部指針。確認原型和實例之間的關係用instanceof。 原型鏈繼承缺點:字面量重寫原型會中斷關係,使用引用類型的原型,並且子類型還無法給超類型傳遞參數 f


1.原型鏈繼承:構造函數、原型和實例的關係:每個構造函數都有一個原型對象,原型對象都包含一個指向構造函數的指針,而實例都包含一個指向原型對象的內部指針。確認原型和實例之間的關係用instanceof。

原型鏈繼承缺點:字面量重寫原型會中斷關係,使用引用類型的原型,並且子類型還無法給超類型傳遞參數

function Parent(){
        this.name='mike';
    }
    function Child(){
        this.age=12;
    }
    //兒子繼承父親(原型鏈)
    Child.prototype=new Parent();//Child繼承Parent,通過原型形成鏈條
    var test=new Child();
    console.log(test.age);
    console.log(test.name);//得到被繼承的屬性
    //孫子繼續原型鏈繼承兒子
    function Brother(){
        this.weight=60;
    }
    Brother.prototype=new Child();//繼承原型鏈繼承
    var brother=new Brother();
    console.log(brother.name);//繼承了Parent和Child,彈出mike
    console.log(brother.age);//12

    console.log(brother instanceof Child);//ture
    console.log(brother instanceof Parent);//ture
    console.log(brother instanceof Object);//ture
View Code

2.構造函數實現繼承:又叫偽造對象或經典繼承。

構造函數實現繼承缺點:借用構造函數雖然解決了原型鏈繼承的兩種問題,但沒有原型,則復用無從談起,所以需要原型鏈+借用構造函數模式。

function Parent(age){
        this.name=['mike','jack','smith'];
        this.age=age;
    }
    function Child(age){
        Parent.call(this,age);//把this指向Parent,同時還可以傳遞參數
    }
    var test=new Child(21);
    console.log(test.age);//21
    console.log(test.name);

    test.name.push('bill');
    console.log(test.name);//mike,jack,smith,bill
View Code

3.組合繼承:使用原型鏈實現對原型屬性和方法的繼承,而通過借用構造函數來實現對實例屬性的繼承。這樣即通過在原型上定義方法實現了函數復用,又保證每個實現都有它自己的屬性。

缺點:無論什麼情況下,都會調用兩次超類型構造函數,一次是在創建子類型原型的時候,另一次是在創建子類型原型的時候,另一次是在子類型構造函數內部。

function Parent(age){
        this.name=['mike','jack','smith'];
        this.age=age;
    }
    Parent.prototype.run=function(){
        return this.name+' are both '+this.age;
    }
    function Child(age){
        Parent.call(this,age);//給超類型傳參,第二次調用
    }
    Child.prototype=new Parent();//原型鏈繼承,第一次調用
    var test1=new Child(21);//寫new Parent(21)也行
    console.log(test1.run());//mike,jack,smith are both 21

    var test2=new Child(22);
    console.log(test2.age);
    console.log(test1.age);
    console.log(test2.run());
    //這樣可以使test1和test2分別擁有自己的屬性age同時又可以有run方法
View Code

4.原型式繼承:藉助原型可以基於已有的對象創建新對象,同時還不必因此創建自定義類型。它要求必須有一個對象可以作為另一個對象的基礎。

function object(o){
        function F(){};
        F.prototype=o;
        return new F();
    }
    var person={
        name:'nicho',
        friends:['shell','jim','lucy']
    }
    var anotherPerson = object(person);
    anotherPerson.name = 'Greg';
    anotherPerson.friends.push('Rob');
    console.log(anotherPerson.friends);//["shell", "jim", "lucy", "Rob"]

    var yetAnotherPerson = object(person);
    yetAnotherPerson.name = 'Linda';
    yetAnotherPerson.friends.push('Barbie');
    console.log(yetAnotherPerson.friends);//["shell", "jim", "lucy", "Rob", "Barbie"]

    console.log(person.friends);//["shell", "jim", "lucy", "Rob", "Barbie"]
View Code

ECMAScript5通過新增Object.create()方法規範化了原型式繼承,這個方法接收兩個參數:一個用作新對象原型的對象和(可選的)一個為新對象定義屬性的對象。

var person2={
        name:'nicho',
        friends:['shell','jim','lucy']
    };
    var anoP2=Object.create(person2);
    anoP2.name="Greg";
    anoP2.friends.push('Rob');
    console.log(anoP2.friends);//["shell", "jim", "lucy", "Rob"]

    var yetP2=Object.create(person2);
    yetP2.name="Linda";
    yetP2.friends.push('Barbie');
    console.log(yetP2.friends);//["shell", "jim", "lucy", "Rob", "Barbie"]

    console.log(person2.friends);//["shell", "jim", "lucy", "Rob", "Barbie"]
    /*以這種方式指定的任何屬性都會覆蓋原型對象上的同名屬性。*/
    var threeP=Object.create(person,{
        name:{value:'red'}
    });
    console.log(threeP.name);//red,如果threeP中無name則輸出person2里的name值nicho
View Code

5.寄生式繼承:思路與寄生構造函數和工廠模式類似,即創建一個僅用於封裝繼承過程的函數,該函數在內部以某種方式來增強對象,最後再像真地是它做了所有工作一樣返回對象。

function object(o){
        function F(){};
        F.prototype=o;
        return new F();
    };
    function createAnother(o){
        var cl=object(o);
        cl.sayHi=function(){
            console.log('hi');
        }
        return cl;
    };
    var person={
        name:'nick',
        friends:['shelby','court','van']
    }
    var anotherPerson=createAnother(person);
    anotherPerson.sayHi();//hi
    console.log(anotherPerson.name);//nick
    console.log(anotherPerson.friends);//["shelby", "court", "van"]

    /*這個例子中的代碼基於 person 返回了一個新對象—— anotherPerson 。 新對象不僅具有 person
     的所有屬性和方法,而且還有自己的 sayHi() 方法*/
View Code

寄生組合式繼承:無論什麼情況下,都會調用兩次超類型構造函數,一次是在創建子類型原型的時候,另一次是在創建子類型原型的時候,另一次是在子類型構造函數內部,這樣子類型最終會包含超類型對象的全部實例屬性,我們不得不在調用子類型構造函數時重寫這些屬性。因此出現了寄生組合式繼承。

6.寄生組合式繼承:借用構造函數來繼承屬性,通過原型鏈的混成形式來繼承方法。基本思路:不必為了指定子類型的原型而調用超類型的構造函數。本質上就是使用寄生式繼承來繼承超類型的原型,然後再將結果指定給子類型的原型。

function SuperType(name){
        this.name=name;
        this.colors=['red','blue','green'];
    }
    SuperType.prototype.sayName=function(){
        console.log(this.name);
    }
    function SubType(name,age){
        SuperType.call(this,name);
        this.age=age;
    }
    function object(o){
        function F(){};
        F.prototype=o;
        return new F();
    };
    /*inheritPrototype此函數第一步是創建超類型原型的一個副本。第二步是為創建的副本添加constructor屬性,
    * 從而彌補因重寫原型而失去的預設的constructor屬性,第三步將新創建的對象(副本)賦值給子類型的原型*/
    function inheritPrototype(subType,superType){
        var prototype=object(superType.prototype);//創建對象
        prototype.constructor=subType;//增強對象
        subType.prototype=prototype;//指定對象
    }
    inheritPrototype(SubType,SuperType);
    SubType.prototype.sayAge=function(){
        console.log(this.age);
    }

    var p=new SubType('xiaoli',24);
    console.log(p.sayName());
    console.log(p.sayAge());
    console.log(p.colors)
View Code

此方法優點:只調用了一次父類SuperType構造函數,並且因此避免了在SubType.prototype上面創建不必要的多餘的屬性。同時原型鏈還能保持不變,還能正常使用instanceof和isPrototypeOf();



 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本節目錄: 什麼是依賴 傳統方式的問題 解決方案 構造函數註入 屬性註入 註入框架 Abp依賴註入框架 註冊 通常註冊 幫助介面 自定義註冊 解析 構造函數 & 屬性註入 IIocResolver & IIocManager 擴展 IShouldInitialize ASP.NET MVC & AS
  • 如有錯誤,希望留言指正。
  • Jeesz是一個分散式的框架,提供項目模塊化、服務化、熱插拔的思想,高度封裝安全性的Java EE快速開發平臺。 Jeesz本身集成Dubbo服務管控、Zookeeper註冊中心、Redis分散式緩存技術、FastDFS分散式文件系統、ActiveMQ非同步消息中間件、Nginx負載均衡等分散式技術 ...
  • $(function(){ $("li").not(":even").css("color","red"); $("li").filter(":odd").css("color","red"); }) $(function(){ $("li").filter(function(index) { re
  • 本人沒有美工功底,學習html5的主要目的也不是為了做網頁設計, 而是學習其腳本語言javascript的編寫, 還有就是CSS. 於是在網上到處找html5開發的資料,html5的開發工具等等。 網上很多朋友都推薦有好幾款開發工具,我也試著下載安裝過有好幾款, 其中網友比較多使用的是dreamwe
  • 選擇器(selector)是CSS中很重要的概念,所有HTML語言中的標記都是通過不同的CSS選擇器進行控制的。用戶只需要通過選擇器對不同的HTML標簽進行控制,並賦予各種樣式聲明,即可實現各種效果。 1. * * { margin: 0; padding: 0; } 星號選擇器用於選取頁面中的所有
  • 近日在群里看到有個題目,拿出來寫寫, 要求: 用html,css,原生js實現如圖的效果,先正向輸出,然後逆向回溯,最後停留在完整的畫面。 首先: HTML部分代碼: <div id="result"></div> 就是這麼簡單一行搞定。 CSS代碼: #result{ width:550px; m
  • [1]定義 [2]方法 [3]相容
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...