類的繼承

来源:https://www.cnblogs.com/walls/archive/2018/07/31/9393686.html
-Advertisement-
Play Games

本文講述JavaScript中類繼承的實現方式,並比較實現方式的差異。 一、何為繼承 繼承,是子類繼承父類的特征和行為,使得子類對象具有父類的實例域和方法。 繼承是面向對象編程中,不可或缺的一部分。 1.1 優點 父類可以為子類提供通用的屬性,而不必因為增加功能,而逐個修改子類的屬性 同上 子類在父 ...


本文講述JavaScript中類繼承的實現方式,並比較實現方式的差異。

一、何為繼承

繼承,是子類繼承父類的特征和行為,使得子類對象具有父類的實例域和方法。
繼承是面向對象編程中,不可或缺的一部分。

1.1 優點

  • 減少代碼冗餘 父類可以為子類提供通用的屬性,而不必因為增加功能,而逐個修改子類的屬性
  • 代碼復用 同上
  • 代碼易於管理和擴展 子類在父類基礎上,可以實現自己的獨特功能

1.2 缺點

  • 耦合度高 如果修改父類代碼,將影響所有繼承於它的子類
  • 影響性能 子類繼承於父類的數據成員,有些是沒有使用價值的。但是,在實例化的時候,已經分配了記憶體。所以,在一定程度上影響程式性能。

二、例子

例子以圖書館中的書入庫歸類為例。
以下是簡化後的父類Book(也可稱為基類)。
目的是通過繼承該父類,產出Computer(電腦)子類。
並且,子類擁有新方法say,輸出自己的書名。

function Book(){
    this.name = ''; // 書名
    this.page = 0; // 頁數
    this.classify = ''; // 類型
}
Book.prototype = {
    constructor: Book,
    init: function(option){
        this.name = option.name || '';
        this.page = option.page || 0;
        this.classify = option.classify || '';
    },
    getName: function(){
        console.log(this.name);
    },
    getPage: function(){
        console.log(this.page);
    },
    getClassify: function(){
        console.log(this.classify);
    }
};

接下來會講解子類Computer幾種繼承方式的實現和優化方法。開始飆車~

三、實例式繼承

function Computer(){
    Book.apply(this, arguments);
}
Computer.prototype = new Book();
Computer.prototype.constructor = Computer;
Computer.prototype.init = function(option){
    option.classify = 'computer';
    Book.prototype.init.call(this, option);
};
Computer.prototype.say = function(){
    console.log('I\'m '+ this.name);
}

3.1 調用父類構造器進行初始化

function Computer(){
    Book.apply(this, arguments);
}

Computer的構造函數里,調用父類的構造函數進行初始化操作。使子類擁有父類一樣的初始化屬性。

3.2 將父類的原型傳遞給子類

Computer.prototype = new Book();使用new操作符對父類Book進行實例化,並將實例對象賦值給子類的prototype
這樣,子類Computer就可以通過原型鏈訪問到父類的屬性。

3.3 缺點

  • 父類Book的構造函數被執行了2次
    • 一次是在Computer的構造函數里Book.apply(this, arguments);
    • 一次是在Computer.prototype = new Book();
      這種模式,存在一定的性能浪費。
  • 父類實例化無法傳參
    Computer.prototype = new Book();,這種實例化方式,無法讓Book父類接收不固定的參數集合。

四、原型式繼承

function Computer(){
    Book.apply(this, arguments);
}
Computer.prototype = Object.create(Book.prototype);
Computer.prototype.constructor = Computer;
Computer.prototype.init = function(option){
    option.classify = 'computer';
    Book.prototype.init(option);
};
Computer.prototype.say = function(){
    console.log('I\'m '+ this.name);
}

這裡的改進:是使用Object.create(Book.prototype)。它的作用是返回一個繼承自原型對象Book.prototype的新對象。且該對象下的屬性已經初始化。
Object.create生成新對象,並不會調用到Book的構造函數。
這種方式,也可以通過原型鏈實現繼承。

五、Object.create的簡單版相容

由於低版本的瀏覽器是不支持Object.create的。所以這裡簡單介紹下相容版本:

Object.create = function(prototype){
    function F(){}
    F.prototype = prototype;
    return new F();
}

原理是定義一個空的構造函數,然後修改其原型,使之成為一個跳板,可以將原型鏈傳遞到真正的prototype。

六、函數化繼承

上述兩種實現方式,都存在一個問題:不存在私有屬性私有方法。也就是說,存在被篡改的風險。
接下來就用函數化來化解這個問題。

function book(spec, my){
    var that = {};

    // 私有變數
    spec.name = spec.name || ''; // 書名
    spec.page = spec.page || 0; // 頁數
    spec.classify = spec.classify || ''; // 類型

    var getName = function(){
        console.log(spec.name);
    };
    var getPage = function(){
        console.log(spec.page);
    };
    var getClassify = function(){
        console.log(spec.classify);
    };

    that.getName = getName;
    that.getPage = getPage;
    that.getClassify = getClassify;

    return that;
}

function computer(spec, my){
    spec = spec || {};
    spec.classify = 'computer';
    var that = book(spec, my);

    var say = function(){
        console.log('I\'m '+ spec.name);
    };
    that.say = say;

    return that;
}

var Ninja = computer({name: 'JavaScript忍者秘籍', page: 350});

函數化的優勢,就是可以更好地進行封裝和信息隱藏。
也許有人疑惑為什麼用以下這種方式聲明和暴露方法:

var say = function(){
    console.log('I\'m '+ spec.name);
};
that.say = say;

其實是為了保護對象自身的完整性。即使that.say被外部篡改或破壞掉,function computer內部的say方法仍然能夠正常工作。
另外,解釋下thatspecmy的作用:

  • that是一個公開數據存儲容器,暴露出去的數據介面,都放到這個容器
  • spec是用來存儲創建新實例所需的信息,屬於實例之間共同編輯的數據
  • my是用來存儲父類、子類之間共用的私密數據容器,外部是訪問不到的。

七、ES6繼承

最後,看下現代版ES6的類繼承。不禁感慨以前的刀耕火種,是多麼折磨人

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

-Advertisement-
Play Games
更多相關文章
  • 打一個比較形象的比喻,把APP比作我們的人體,把胳膊、大腿、心、肝、肺這些人體器官比作組件,各個器官分別負責他們各自的功能,但是他們之間也有主次之分,試想我們的胳膊、大腿等是不能獨立完成某個任務的,必須需要心、肺、肝、膽等的能量支持,那麼可以把胳膊、大腿這種功能性器官比作業務組件,把我們的心、肝、脾 ...
  • 女孩:BroadcastReceiver是什麼呀? 男孩:Broadcast是廣播的意思,在Android中應用程式之間的傳輸信息的機制,BroadcastReceiver是接收廣播通知的組件,廣播和廣播接收器是Android中需要瞭解的,那麼怎麼樣去瞭解呢~ 廣播,大家應該可以理解,我們在學校做眼 ...
  • 1.使用 工具欄 -> Analyze -> Inspect Code… 點擊 Inspect Code 後會彈出檢查範圍的對話框: 預設是檢查整個項目,我們可以點擊 Custom scope 自定義檢查範圍。 點擊右邊的下拉框,會出現以下選擇: 分別有: Project Files:所有項目文件 ...
  • 安裝APK 發送請求獲取輸入流 解析XML文件 可以開始下載 跟蹤下載進度 下載完畢啟動安裝 獲取項目包名 ...
  • 系統路徑 文件操作 資源文件assets和RW res/raw:文件會被映射到R.java文件中,訪問的時候直接通過資源ID訪問,沒有有目錄結構 assets:不會映射到R.java文件中,通過AssetManager來訪問,能有目錄結構 從資源文件中獲取Bitmap ...
  • ios的viewcontroller生命周期是 init -> loadView -> viewDidLoad -> viewWillAppear -> viewDidAppear -> viewWillDisappear -> viewDidAppear -> viewDidUnload -> d ...
  • Preface Android中,Client測量和計算佈局,SurfaceFlienger(server)用來渲染繪製界面,client和server的是通過匿名共用記憶體(SharedClient)通信。 每個應用和SurfaceFlienger之間都會創建一個SharedClient,一個Sha ...
  • 一,效果圖。 二,代碼。 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Todo</title> <meta name="viewport" content="initial-scale=1, maximum-scale=1, ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...