国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

mixin配合class實現多繼承的絕佳妙用

DevTTL / 1056人閱讀

摘要:源碼地址什么是一般翻譯為混入混合,早期一般解釋為把一個對象的方法和屬性拷貝到另一個對象上也可以簡單理解為能夠被繼承的類,最終目的是實現代碼的復用。

Github 源碼地址

什么是mixin

mixin一般翻譯為“混入”、“混合”,
早期一般解釋為:把一個對象的方法和屬性拷貝到另一個對象上;
也可以簡單理解為能夠被繼承的類,
最終目的是實現代碼的復用。

從一個需求說起

為了使你能夠最快的清楚我在說什么,我們從一個需求說起:

一個項目中有多個彈層需求;
一些是公共方法,比如點擊關閉按鈕關閉彈層;
一些彈層是可以拖動的,且有蒙層;
一些彈層是可以縮放的;
其他都是業務方法,無可復用性。

你可以先在心里想下,如果是你,你會怎樣完成這個需求?

腦海中規劃下

我們為公共方法寫個類:BaseModal
為可拖動的彈層寫個類:DragModal
為可縮放的彈層寫個類:ScaleModal
為自定義的業務需求寫個類:CustomModal

畫個腦圖的話,會是下面圖片中的樣子:

extends簡單實現下 看代碼
// 公共方法
class BaseModal {
  close(){
    console.log("close");
  }
}

// 可以拖動的彈層,我們寫一個多帶帶的類
class DragModal extends BaseModal {
  hasLayer = true;
  drag() {
    console.log("drag");
  }
}

// 可以縮放的彈層,我們寫一個多帶帶的類
class ScaleModal extends BaseModal {
  scale() {
    console.log("scale");
  }
}

// 業務方法
class CustomModal extends DragModal {
  close(){
    console.log("custom-close");
  }
  do() {
    console.log("do");
  }
}

let c = new CustomModal();
c.close(); // custom-close
c.drag(); // drag
c.do(); // do
c.hasLayer; // true
拋出問題

如何使CustomModal能夠同時繼承DragModalScaleModal

某個相同方法希望不覆蓋,而是都執行

試試早期的mixin方法實現多繼承 看代碼
// 可以拖動的彈層,我們寫一個多帶帶的類
class DragModal extends BaseModal {
  hasLayer = true;
  drag() {
    console.log("drag");
  }
}

// 可以縮放的彈層,我們寫一個多帶帶的類
class ScaleModal extends BaseModal {
  scale() {
    console.log("scale");
  }
}

// 獲取原型對象的所有屬性和方法
function getPrototypes(ClassPrototype) {
  return Object.getOwnPropertyNames(ClassPrototype).slice(1);
}

function mix(...mixins){
  return function(target){
    if (!mixins || !Array.isArray(mixins)) return target;
    let cp = target.prototype;
    for (let C of mixins) {
      let mp = C.prototype;
      for (let m of getPrototypes(mp)) {
        cp[m] = mp[m];
      }
    }
  }
}
@mix(DragModal, ScaleModal)
class CustomModal {
  scale(){
    console.log("custom-scale");
  } 
  do() {
    console.log("do");
  }
}
let c = new CustomModal();
c.close(); // 報錯,因為dobase沒在A或B的prototype上,而是在A.prototype.__proto__上
c.drag(); // drag
c.scale(); // scale  并非是我們想要的custom-scale
console.log(c.hasLayer); // undefined
存在的問題

以上mix方式實現了多繼承,但存在以下問題

會修改target類的原型對象

target類的相同方法名會被被繼承類的相同方法名覆蓋

實例屬性無法繼承

BaseModal類無法被繼承

只繼承不修改prototype的實現方式 看代碼
class BaseModal {
  close() {
    console.log("close");
  }
}

let DragModalMixin = (extendsClass) => class extends extendsClass {
  hasLayer = true;
  drag() {
    console.log("drag");
  }
};

class CustomModal extends DragModalMixin(BaseModal) {
  drag() {
    console.log("custom-drag");
  }
  do() {
    console.log("do");
  }
}

let c = new CustomModal();

c.close(); // close
c.drag(); // custom-drag
console.log(c.hasLayer); // true
存在的問題

如何讓CustomModal再繼承ScaleModal呢?
其實很簡單,在上面基礎上,我們再寫一個ScaleModalMixinMixin類就可以了

完美的多繼承 看代碼
class BaseModal {
  close() {
    console.log("close");
  }
}

let DragModalMixin = (extendsClass) => class extends extendsClass {
  hasLayer = true;
  drag() {
    console.log("drag");
  }
};

let ScaleModalMixin = (extendsClass) => class extends extendsClass {
  scale() {
    console.log("scale");
  }
};

class CustomModal extends ScaleModalMixin(DragModalMixin(BaseModal)) {
  drag() {
    console.log("custom-drag");
  }
  do() {
    console.log("do");
  }
}

let c = new CustomModal();

c.close(); // close
c.drag(); // custom-drag
c.scale(); // scale
console.log(c.hasLayer); // true
存在的問題

這種方式不會修改父類的原型對象,但是如果存在跟父類同名的方法,只會執行父類的,而不回執行被繼承的類的方法,那么如何使相同方法分別執行呢?

super實現相同方法不覆蓋 看代碼
class BaseModal {
  close() {
    console.log("close");
  }
}

let DragModalMixin = (extendsClass) => class extends extendsClass {
  hasLayer = true;
  drag() {
    console.log("drag");
  }
};
let ScaleModalMixin = (extendsClass) => class extends extendsClass {
  scale() {
    console.log("scale");
  }
  close() {
    console.log("scale-close");
    if (super.close) super.close();
  }
};

class CustomModal extends ScaleModalMixin(DragModalMixin(BaseModal)) {
  close() {
    console.log("custom-close");
    if (super.close) super.close();
  }
  do() {
    console.log("do");
  }
}

let c = new CustomModal();

c.close(); // custom-close   ->   scale-close   ->   close
總結

Mixin是一種思想,用來實現代碼高度可復用性,又可以用來解決多繼承的問題,是一種非常靈活的設計模式,如果你多多琢磨,相信你也會發現一些其他的妙用的,看好你喲!

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95713.html

相關文章

  • 妙用協程】 - 單元測試setUp和tearDown

    摘要:一般的做法是把這些動作寫在和的兩個方法里,單元測試框架會負責在開始和結束的時候調用這兩個方法。從視覺上無法直觀的指導原來和是一對的。然后再把這個小的上下文附著到主測試邏輯上這里利用了單元測試的的特性,把轉化為回調在的時候就設置好。 很多測試都需要在啟動的時候做一些事情,然后在結束的時候再把做的事情給清理了。一般的做法是把這些動作寫在setUp和tearDown的兩個方法里,單元測試框架...

    MartinDai 評論0 收藏0
  • Javascript裝飾器妙用

    摘要:最近新開了一個項目,采用來開發,在數據庫及路由管理方面用了不少的裝飾器,發覺這的確是一個好東西。在中的使用該裝飾器會在定義前調用,如果函數有返回值,則會認為是一個新的構造函數來替代之前的構造函數。函數參數裝飾器最后,還有一個用于函數參 最近新開了一個Node項目,采用TypeScript來開發,在數據庫及路由管理方面用了不少的裝飾器,發覺這的確是一個好東西。 裝飾器是一個還處于草案中...

    phodal 評論0 收藏0
  • Vue with typescript

    摘要:想要使用語法的話,配合,這個插件,體驗更佳,這個插件在語法中實現了。這種方式最接近的單文件組件的寫法,如果一個完善項目從改成,用這種方法很快,只要加上和一些必要的變量類型就好了,然后用包裹就好。不推薦混入用這種方式寫,無法實現多繼承。 最近嘗試了一下 TypeScript,試著把一個 Vue 項目改成了 TypeScript 的,感覺還不錯 目前 Vue 和 TypeScript 的配...

    JerryWangSAP 評論0 收藏0
  • CSS border屬性--妙用

    摘要:在下實現圓角效果由于兼容性特別差,所以要在低版本瀏覽器下實現圓周角效果特別難利用的效果可實現如下圖所示的圓效果代碼簡單如下制作三杠效果其實就是利用特性變色我們在做如下圖標時,一般情況下時會有三處變色但是利用繼承自這一特性 在ie下實現圓角效果 (由于border-radius兼容性特別差,所以要在ie低版本瀏覽器下實現圓周角效果特別難)利用border-style的dotted效果可實...

    heartFollower 評論0 收藏0
  • 談談CSS預處理器

    摘要:變量插值預處理器中定義的變量不僅可以用作屬性值,還可以用作選擇器,屬性名等,這就是變量插值。三種預處理器的嵌套語法是一致的,引用父級選擇器的標記也相同。三種預處理器的使用方式的差異比較大,下面分別說明。 在寫CSS的時候我們會發現,為了兼容瀏覽器等原因,我們往往需要寫很多冗余的代碼,CSS預處理器就是為了解決CSS的這些問題,簡化CSS代碼的編寫。 目前最主流的CSS預處理器是LESS...

    BlackMass 評論0 收藏0

發表評論

0條評論

DevTTL

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<