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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...