<font id="zqva1"></font>
<rt id="zqva1"></rt>
  • <tt id="zqva1"></tt>
    <cite id="zqva1"></cite>

    <cite id="zqva1"><noscript id="zqva1"></noscript></cite>
      <rp id="zqva1"><meter id="zqva1"></meter></rp>

        <cite id="zqva1"></cite>
          <b id="zqva1"></b>
          <rp id="zqva1"></rp>
          <cite id="zqva1"></cite>

          <rt id="zqva1"></rt>

        1. <rp id="zqva1"></rp>

          Js繼承實現小結:JavaScript實現繼承的6種方式

          時間:?2017-12-22閱讀:?708標簽:?js知識

          前言

          JS作為面向對象的弱類型語言,繼承也是其非常強大的特性之一。那么如何在JS中實現繼承呢?讓我們拭目以待。


          JS繼承的實現方式

          既然要實現繼承,那么首先我們得有一個父類,代碼如下:

          // 定義一個動物類
          function Animal (name) {
            // 屬性
            this.name = name || 'Animal';
            // 實例方法
            this.sleep = function(){
              console.log(this.name + '正在睡覺!');
            }
          }
          // 原型方法
          Animal.prototype.eat = function(food) {
            console.log(this.name + '正在吃:' + food);
          };
          


          1、原型鏈繼承

          核心: 將父類的實例作為子類的原型

          function Cat(){ 
          }
          Cat.prototype = new Animal();
          Cat.prototype.name = 'cat';
          
          // Test Code
          var cat = new Cat();
          console.log(cat.name);
          console.log(cat.eat('fish'));
          console.log(cat.sleep());
          console.log(cat instanceof Animal); //true 
          console.log(cat instanceof Cat); //true
          

          特點:

          1. 非常純粹的繼承關系,實例是子類的實例,也是父類的實例
          2. 父類新增原型方法/原型屬性,子類都能訪問到
          3. 簡單,易于實現

          缺點:

          1. 要想為子類新增屬性和方法,必須要在new Animal()這樣的語句之后執行,不能放到構造器中
          2. 無法實現多繼承
          3. 來自原型對象的引用屬性是所有實例共享的
          4. 創建子類實例時,無法向父類構造函數傳參

          推薦指數:★★(3、4兩大致命缺陷)

          缺點1中描述有誤:可以在Cat構造函數中,為Cat實例增加實例屬性。如果要新增原型屬性和方法,則必須放在new Animal()這樣的語句之后執行。


          2、構造繼承

          核心:使用父類的構造函數來增強子類實例,等于是復制父類的實例屬性給子類(沒用到原型)

          function Cat(name){
            Animal.call(this);
            this.name = name || 'Tom';
          }
          
          // Test Code
          var cat = new Cat();
          console.log(cat.name);
          console.log(cat.sleep());
          console.log(cat instanceof Animal); // false
          console.log(cat instanceof Cat); // true
          

          特點:

          1. 解決了1中,子類實例共享父類引用屬性的問題
          2. 創建子類實例時,可以向父類傳遞參數
          3. 可以實現多繼承(call多個父類對象)

          缺點:

          1. 實例并不是父類的實例,只是子類的實例
          2. 只能繼承父類的實例屬性和方法,不能繼承原型屬性/方法
          3. 無法實現函數復用,每個子類都有父類實例函數的副本,影響性能

          推薦指數:★★(缺點3)


          3、實例繼承

          核心:為父類實例添加新特性,作為子類實例返回

          function Cat(name){
            var instance = new Animal();
            instance.name = name || 'Tom';
            return instance;
          }
          
          // Test Code
          var cat = new Cat();
          console.log(cat.name);
          console.log(cat.sleep());
          console.log(cat instanceof Animal); // true
          console.log(cat instanceof Cat); // false
          

          特點:

          1. 不限制調用方式,不管是new 子類()還是子類(),返回的對象具有相同的效果

          缺點:

          1. 實例是父類的實例,不是子類的實例
          2. 不支持多繼承

          推薦指數:★★


          4、拷貝繼承

          function Cat(name){
            var animal = new Animal();
            for(var p in animal){
              Cat.prototype[p] = animal[p];
            }
            Cat.prototype.name = name || 'Tom';
          }
          
          // Test Code
          var cat = new Cat();
          console.log(cat.name);
          console.log(cat.sleep());
          console.log(cat instanceof Animal); // false
          console.log(cat instanceof Cat); // true
          

          特點:

          1. 支持多繼承

          缺點:

          1. 效率較低,內存占用高(因為要拷貝父類的屬性)
          2. 無法獲取父類不可枚舉的方法(不可枚舉方法,不能使用for in 訪問到)

          推薦指數:★(缺點1)


          5、組合繼承

          核心:通過調用父類構造,繼承父類的屬性并保留傳參的優點,然后通過將父類實例作為子類原型,實現函數復用

          function Cat(name){
            Animal.call(this);
            this.name = name || 'Tom';
          }
          Cat.prototype = new Animal();

          //組合繼承也是需要修復構造函數指向的。

          Cat.prototype.constructor = Cat;
          // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); // true

          特點:

          1. 彌補了方式2的缺陷,可以繼承實例屬性/方法,也可以繼承原型屬性/方法
          2. 既是子類的實例,也是父類的實例
          3. 不存在引用屬性共享問題
          4. 可傳參
          5. 函數可復用

          缺點:

          1. 調用了兩次父類構造函數,生成了兩份實例(子類實例將子類原型上的那份屏蔽了)

          推薦指數:★★★★(僅僅多消耗了一點內存)


          6、寄生組合繼承

          核心:通過寄生方式,砍掉父類的實例屬性,這樣,在調用兩次父類的構造的時候,就不會初始化兩次實例方法/屬性,避免的組合繼承的缺點

          function Cat(name){
            Animal.call(this);
            this.name = name || 'Tom';
          }
          (function(){
            // 創建一個沒有實例方法的類
            var Super = function(){};
            Super.prototype = Animal.prototype;
            //將實例作為子類的原型
            Cat.prototype = new Super();
          })();
          
          // Test Code
          var cat = new Cat();
          console.log(cat.name);
          console.log(cat.sleep());
          console.log(cat instanceof Animal); // true
          console.log(cat instanceof Cat); //true

          //該實現沒有修復constructor。

          Cat.prototype.constructor = Cat; // 需要修復下構造函數

          特點:

          1. 堪稱完美

          缺點:

          1. 實現較為復雜

          推薦指數:★★★★(實現復雜,扣掉一顆星)


          附錄代碼:

          示例一:

          function Animal (name) {
            // 屬性
            this.name = name || 'Animal';
            // 實例方法
            this.sleep = function(){
              console.log(this.name + '正在睡覺!');
            }
            //實例引用屬性
            this.features = [];
          }
          function Cat(name){
          }
          Cat.prototype = new Animal();
          
          var tom = new Cat('Tom');
          var kissy = new Cat('Kissy');
          
          console.log(tom.name); // "Animal"
          console.log(kissy.name); // "Animal"
          console.log(tom.features); // []
          console.log(kissy.features); // []
          
          tom.name = 'Tom-New Name';
          tom.features.push('eat');
          
          //針對父類實例值類型成員的更改,不影響
          console.log(tom.name); // "Tom-New Name"
          console.log(kissy.name); // "Animal"
          //針對父類實例引用類型成員的更改,會通過影響其他子類實例
          console.log(tom.features); // ['eat']
          console.log(kissy.features); // ['eat']
          

          原因分析: 關鍵點:屬性查找過程 執行tom.features.push,首先找tom對象的實例屬性(找不到), 那么去原型對象中找,也就是Animal的實例。發現有,那么就直接在這個對象的 features屬性中插入值。 在console.log(kissy.features); 的時候。同上,kissy實例上沒有,那么去原型上找。 剛好原型上有,就直接返回,但是注意,這個原型對象中features屬性值已經變化了。


          站長推薦

          1.阿里云: 本站目前使用的是阿里云主機,安全/可靠/穩定。點擊領取2000元代金券、了解最新阿里云產品的各種優惠活動點擊進入

          2.騰訊云: 提供云服務器、云數據庫、云存儲、視頻與CDN、域名等服務。騰訊云各類產品的最新活動,優惠券領取點擊進入

          3.廣告聯盟: 整理了目前主流的廣告聯盟平臺,如果你有流量,可以作為參考選擇適合你的平臺點擊進入

          鏈接: http://www.modern-decoration.com.cn/article/detial/275

          javascript中什么是句柄?

          一個句柄是指使用的一個唯一的整數值,即一個4字節(64位程序中為8字節)長的數值,來標識應用程序中的不同對象和同類中的不同的實例。

          javascript不可變性是什么?

          不可變性即某個變量在進行了某個操作之后,其本身沒有發生變化,比如對于字符串而言,對字符串的任何操作都會改變字符串本身的值,而是在字符串的基礎上復制出來一個然后再改變,這樣我們就說是不可變的

          為什么javascript不起作用?

          JavaScript是一種屬于網絡的腳本語言,已經被廣泛用于Web應用開發,常用來為網頁添加各式各樣的動態功能,為用戶提供更流暢美觀的瀏覽效果。通常JavaScript腳本是通過嵌入在HTML中來實現自身的功能的。

          javascript怎么判斷按鈕被點擊?

          JavaScript可以通過Event對象的target事件或srcElement(IE瀏覽器支持)來判斷按鈕是否被點擊。Event對象代表事件的狀態,比如事件在其中發生的元素、鍵盤按鍵的狀態、鼠標的位置、鼠標按鈕的狀態。

          javascript由幾部分組成?

          JavaScript有三部分組成。分別為核心(ECMAScript) 、文檔對象模型(DOM)、瀏覽器對象模型(BOM)。這三部分分別描述了該語言的語法和基本對象、處理網頁內容的方法和接口、與瀏覽器進行交互的方法和接口。

          Js輸出方式有哪些?

          在編寫JavaScript代碼的時候, 一定要記住每一句代碼后面都需要添加一個分號, 并且這個分號必須是英文的分號,我們會發現有時候不寫分號程序也能夠運行, 這里并不是因為不需要分號, 而是瀏覽器自動幫助我們添加了分號

          7個常見的 JavaScript 測驗及解答

          我相信學習新事物并評估我們所知的東西對自己的進步非常有用,可以避免了我們覺得自己的知識過時的情況。在本文中,我將介紹一些常見的 JavaScript 知識。請享用!

          Js中constructor指向問題

          首先用一個例子指出來constructor存在形式。由上面的代碼我們總結出結論1:上面的代碼在控制臺可以看出constructor是指向構造器Fruit的引用。這個地方就有點奇怪了。這個constructor到底指向的是那個實例的構造器?

          javascript難點是什么?

          javascript難點是什么?下面本篇文章就來給大家介紹一下10個JavaScript難點,感興趣的小伙伴們可以參考一下,希望對大家有所幫助。立即執行函數,即Immediately Invoked Function Expression (IIFE),正如它的名字

          Js如何獲取ul中li的個數?

          javascript如何獲取ul中li的個數?下面本篇文章就來給大家介紹一下使用javascript獲取ul中li個數的方法,希望對大家有所幫助。

          內容以共享、參考、研究為目的,不存在任何商業目的。其版權屬原作者所有,如有侵權或違規,請與小編聯系!情況屬實本人將予以刪除!

          文章投稿關于web前端網站點搜索站長推薦網站地圖站長QQ:522607023

          小程序專欄: 土味情話心理測試腦筋急轉彎幽默笑話段子句子語錄成語大全運營推廣

          国产精品高清视频免费 - 视频 - 在线观看 - 影视资讯 - 唯爱网