總結繼承的幾種方式

簡單總結繼承的幾種方式

JavaScript作為一門弱類型的語言,本著精簡的原則,它取消了類的概念,只有對象的概念,

更是有萬物皆對象的說法。在基于類的面向對象方式中,對象(object)依靠類(class)來產生。

而在基于原型的面向對象方式中,對象(object)則是依靠構造器(constructor) 利用 原型(prototype)

構造出來的。而JavaScript語言正是如此,它是通過一種叫做原型(prototype)的方式來實現面向對象編程的。

它和其他的面向對象類編程語言一樣,只是它的實現方式不同而已,或者說他們采用了不同的面向對象設計哲學。

那么下面就讓我們來簡單總結一下繼承的幾種方式:

  1. 擴展原型對象實現繼承

構造函數有一個 prototype 屬性,指向的就是原型對象,通過給原型對象添加屬性和方法,讓構造函數的實例

都可以訪問到,從而實現繼承

function Animal(name,color,say){this.name = name;this.color = color;this.say = function(){console.log('喵喵喵');}
}var cat = new Animal('cat','white');
// 如果給Animal的prototype屬性上添加個 cry 方法 ,那么實例對象 cat將也會有 cry方法 
Animal.prototype.cry = function(){console.log('嗚嗚嗚');
}
  1. 替換原型對象實現繼承 (常用類型)
  • 為什么會有該方式呢?
    其實上面擴展原型對象的方法已經很方便了,但是為什么我們還需要使用該方式呢?試想一下,
    當我們需要給構造函數的原型對象添加許多屬性和方法的時候,豈不是要寫很多冗余(重復)的代碼。例如上面的例子
    看下面代碼:

        // 我們要給 構造函數Animal 添加很多的方法 即:Animal.prototype.aaa = function(){};Animal.prototype.bbb = function(){};Animal.prototype.ccc = function(){};Animal.prototype.ddd = function(){};Animal.prototype.eee = function(){};......  // 諸如這樣的話,代碼就顯得不那么優雅,高效了吧。
  • 實現方式?
    重新給構造函數的prototype屬性(原型對象)賦值,指向一個全新的對象,在這個對象中添加屬性和方法,注:
    一定要添加一個constructor屬性,并且指向構造函數本身 具體看代碼:

        Animal.prototype = {// 一定要指明constructor屬性,不然的話,會根據原型鏈查找一直到Object.prototypeconstructor : Animal;  saying : function(){},crying : function(){},doing : function(){}......}
  1. 混入繼承
  • 混入繼承的使用場景:已知對象 o1, o2, 需要把 o1中的功能(屬性方法)拷貝到 o2 中去
  • 實現方式 :用 for...in... 對 o 進行遍歷(可以將混入繼承的模式封裝成函數),如下所示

      // target : 目標對象(接收數據的對象)// source : 接收對象 (數據從哪個對象中來)function mixin(target,source){for(var key in source){target[key] = source[key];}return target;}
  • 原理其實很簡單,jQuery中的$.extend 方法利用的就是混入繼承的原理

  1. 原型 + 混入繼承
  • 本質上就是對混入繼承的一次運用
  • 只不過目標對象為原型對象而已

          // 運用上面封裝的混入繼承的函數  將對象{a:10,b:20,c:function(){}}的功能考本到Animal原型對象上去mixin(Animal.prototype, {a:10,b:20,c:function(){}} );  // 還可以 這樣操作 給Animal構造函數 的原型對象添加一個extend方法,在該方法中調用mixin函數,這樣的話也可以實現Animal.prototype.extend = function(){mixin(Animal.prototype, source);}// 不過兩種方法沒有本質之差,看大家易于接受哪個了
  1. 經典繼承 —> 道格拉斯《JavaScript語言精粹》中提到的一種繼承模型
  • 實現的功能:已知一個對象 o1 需要創建一個新的對象 o2 ,這個新的對象需要繼承自對象 o1,代碼如下:

        // 可以將經典繼承 封裝成一個函數function create(o){function F(){};    // 創建一個構造函數F.prototype = o;   // 將F 的原型指向 對象 o;return new F();    // 將 構造函數的實例 返回出去,這樣的話 F的實例對象,就會繼承自 o}var o2 = create(o1);  // 即:o2 繼承于 o1 ;  o2.__proto__ = o1;
  • 使用場景 :要創建一個對象(不需要關心構造函數),新對象需要繼承自另一個指定的對象
  • ES5中 :Object.create( ) 的實現原理就源自于經典繼承

  1. 借用構造函數 實現繼承
  • 先看一下代碼 再解釋:

      // 需要兩個構造函數function Person(name,age,gender){  this.name = name;this.age = age;this.gender = gender;}// function Student(name,age,){//  this.name = name;// this.age = age;//  this.gender = gender;// }// 這樣的話 name,age 屬性都一樣,就會產生重復的代碼 我們可以巧妙的利用call 來簡單的實現function Student(name,age){Person.call(this,name,age);     // 其實就是用 call的方法,call借用Person的功能this.gender = gender;}
    • 借用Person中的構造函數的功能,this表示構造函數的實例,即Student的實例對象可以繼承name,age屬性;
    • 借用構造函數實現繼承,子構造函數借用父構造函數來完成,給子類Student的實例添加屬性
    • 注意:由于要借用父類構造函數,所以父類構造函數的功能對子類對象要適用,例如下面情況就最好不用call

      // 需要兩個構造函數
      function Person(name,age,gender){  this.name = name;this.age = age;this.gender = gender;
      }
      // function Student(name,age,){
      //  this.name = name;
      // this.age = age;
      // }
      function Student(name,age){Person.call(this,name,age);     
      }
  • 上述情況,就最好不要使用call來借用父類構造函數Person的功能了,因為,gender屬性是Student子類構造函數
    并不需要的,這樣的話,就會在Student中產生不必要的屬性和方法,如果子類函數還要有gender方法的話,那么就會和之前的產生沖突,交叉污染
  • 其他情況:遇到需要實現功能,該對象上沒有這個功能,可以適當地去尋找已經有功能的對象

轉載于:https://www.cnblogs.com/guoqi77/p/Q_Inherit.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/372070.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/372070.shtml
英文地址,請注明出處:http://en.pswp.cn/news/372070.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Oracle SQL精妙SQL語句講解(二)

- 如果存在就更新,不存在就插入用一個語句實現 DROP TABLE t_mg; CREATE TABLE t_mg(code VARCHAR2(10), NAME VARCHAR2(10)); SELECT * FROM t_mg; MERGE INTO t_mg a USING (SELECT the code code, the name NAME FROM dual) b ON (a.code b.code) WHEN M…

Spring Security –在一個應用程序中有兩個安全領域

這篇博客文章主要是關于Spring Security配置的。 更具體地說,它打算顯示如何在一個Web應用程序中配置兩個不同的安全領域。 第一安全領域是針對瀏覽器客戶端的。 它使我們能夠在登錄頁面中登錄并訪問受保護的資源。 第二安全領域旨在處理來自android應用程序的REST…

基于Activiti工作流引擎實現的請假審核流程

概要 本文檔介紹的是某商用中集成的Activiti工作流的部署及使用,該框架用的Activiti版本為5.19.0。本文檔中主要以一個請假流程為例子進行說明,該例子的流程圖如下: 這是一個可以正常運作的工作流業務了,但是它也有不足的地方&…

linux編譯ffmpeg成so,「ffmpeg」一 mac 環境下編譯ffmpeg,生成so庫文件

1.下載ffmpeg源碼,官網,我這里直接采用git 方式下載:下載ffmpeg.png終端輸入git命令:靜靜等待~最后下載的版本為3.4.6 。image.png這里注意一下,剛開始我用的ndk版本是ndk-17b,在編譯該版本的ffmpeg時始終失敗&#xf…

4Web Service中的幾個重要術語

4.1WSDL: web service definition language 直譯:Webservice定義語言 1.對應一種類型的文件.wsdl 2.定義了webservice的服務端與客戶端應用交互傳遞請求和響應數據的格式和方式 3.一個webservice對應一個唯一的esdl文檔 4.2SOAP: simple object access protocal 直譯:簡單對象訪…

云端:亞馬遜,谷歌應用引擎,Windows Azure,Heroku,Jelastic

您想在云端嗎? 您有很多選擇。 我已經評估或使用了許多方法,因此這里有幾句話。 (當我使用Java時,我將包括一些與Java相關的注釋,但大多數情況適用于所有(受支持的)語言。) 但是在深…

JS-字符串操作-替換

<!DOCTYPE HTML><html><head><meta http-equiv"Content-Type" content"text/html; charsetutf-8"><title>無標題文檔</title><style>p { border:10px solid #ccc; background:#FFC; width:400px; padding:20px;…

linux下kegg注釋軟件,KEGG數據中全部代謝反應和代謝物注釋信息的下載

# 加載函數與R包 -----------------------------------------------------------------library(KEGGREST)library(plyr)source("./RbioRXN-master/RbioRXN-master/R/get.kegg.all.R")source("./RbioRXN-master/RbioRXN-master/R/get.kegg.byId.R")## KEGG數…

java常見異常

算術異常類&#xff1a;ArithmeticExecption空指針異常類&#xff1a;NullPointerException 類型強制轉換異常&#xff1a;ClassCastException 數組負下標異常&#xff1a;NegativeArrayException 數組下標越界異常&#xff1a;ArrayIndexOutOfBoundsException 違背安全原則異常…

Spring Security 3 Ajax登錄–訪問受保護的資源

我看過一些有關Spring Security 3 Ajax登錄的博客&#xff0c;但是我找不到解決如何調用基于Ajax的登錄的博客&#xff0c;匿名用戶正在Ajax中訪問受保護的資源。 問題 – Web應用程序允許匿名訪問某些部分&#xff0c;并且某些部分是受保護的資源&#xff0c;需要用戶登錄。 …

測試環境下將centos6.8升級到centos7的操作記錄(轉)

在測試環境下安裝openstack&#xff0c;由于在centos6下安裝openstack&#xff0c;針對源的問題有很多&#xff0c;安裝起來很不順利&#xff01; 但是在centos7下安裝卻很順利&#xff0c;所以考慮將服務器由centos6升級到centos7 這個我是在測試機中運行的&#xff0c;建議不…

linux運維選擇題,初學Linux練習題

1、將/etc/issue文件中的內容轉換為大寫后保存至/tmp/issue.out文件中tr ‘a-z’ ‘A-Z’ < /etc/issue > /tmp/issue.out2、將當前系統登錄用戶的信息轉換為大寫后保存至/tmp/who.out文件中3、一個linux用戶給root發郵件&#xff0c;要求郵件標題為”help”&#xff0c…

[轉]Web Api系列教程第2季(OData篇)(二)——使用Web Api創建只讀的OData服務

本文轉自&#xff1a;http://www.cnblogs.com/fzrain/p/3923727.html 前言 很久沒更新了&#xff0c;之前有很多事情&#xff0c;所以拖了很久&#xff0c;非常抱歉。好了&#xff0c;廢話不多說&#xff0c;下面開始正題。本篇仍然使用上一季的的項目背景&#xff08;系列地址…

使用Spring 3 MVC處理表單

本文是有關Spring 3的一系列文章的一部分。該系列的上一篇文章可以在此處獲得 。 在本文中&#xff0c;我們向Spring MVC邁出了又一步。 [此外&#xff1a; 術語MVC的創建者提供的pdf 。]從上一篇文章構建&#xff0c;讓我們添加將“聯系人”添加到應用程序所需的代碼。 首先&a…

插入排序法之——直接插入排序、折半插入排序、希爾排序

// test20.cpp : 定義控制臺應用程序的入口點。 // #include "stdafx.h" #include<iostream> #include<vector> #include<string> #include<queue> #include<stack> #include<cstring> #include<string.h> #include<de…

linux idea 快捷鍵,Linux 下 IDEA 的 Ctrl+Alt+S

前言這是個困擾我一年多的問題&#xff0c;今天終于解決了……起因一年前將主系統換成 Arch Linux 后&#xff0c;其他一切正常就是 IDEA 的打開設置的快捷鍵 ctrlalts 失效&#xff0c;讓我很是頭疼。雖然不是很重要&#xff0c;但是對于我這種強迫癥來說別提多難受了……我曾…

修改input的placeholder顏色

1、CSS選擇器 因為每個瀏覽器的CSS選擇器有所差異&#xff0c;所以需要針對每個瀏覽器做單獨的設定。 ::-webkit-input-placeholder { /* WebKit browsers */ color: #999; } :-moz-placeholder { /* Mozilla Firefox 4 to 18 */ color: #999; } ::-moz-placeholder { /* Mozil…

解決Spring自動裝配中的循環依賴

我認為這篇文章是在企業應用程序開發中使用Spring的最佳實踐。 使用Spring編寫企業Web應用程序時&#xff0c;服務層中的服務量可能會增加。 服務層中的每個服務可能會消耗其他服務&#xff0c;這些服務將通過Autowire注入。 問題&#xff1a;當服務數量開始增加時&#xff0…

01.MD5加密

namespace _01.MD5加密{ class Program { static void Main(string[] args) { //MD5加密就是給想要的密碼或者其它字符加密 //如果字符串被加密成MD5值之后,是不可逆的. //字符串123 的MD5 64位加密形式是 202cb962ac59075b964b07152d234b70 Console.WriteLine("請輸入需要…

C語言數字3轉變字符 3 程序,大學c語言知識點總結

大學c語言知識點總結C語言的設計目標是提供一種能以簡易的方式編譯、處理低級存儲器、產生少量的機器碼以及不需要任何運行環境支持便能運行的編程語言。一起來看看大學c語言知識點總結吧!大學c語言知識點總結1、編譯預處理不是C語言的一部分&#xff0c;不再運行時間。C語言編…