JS中的Minix和装饰器实现
Minix和裝飾器
Mixin
Mixin 是面向對象語言中一種常用的設計模式,通常稱之為組合,在js中通常使用一個中間的繼承對象實現。
A對象有功能a,C對象需要繼承自A對象并添加x功能,
解決辦法1:我們可以使用C繼承自A,再在C上定義x功能。但是如果D類型需要繼承自B類型,同樣也需要該x功能,我們就只能重寫一遍功能。
解決方法2:將x功能進行封裝到一個Mixin函數中,Mixin函數接受類型A作為參數,然后在這個Mixin函數中創建一個新的類型Temp,Temp繼承A并添加該x功能。這樣C只需要繼承這個新建的Temp就可以同時擁有A和x功能了。這種方式將類型A作為參數。同樣的,如果B類型的子類想添加這個x功能,只需要將B作為參數傳入這個Mixin函數,然后繼承這個函數的返回值。
代碼簡單實現
class A { // 普通類型A,他只能打印它的x屬性,無法打印y和z屬性
constructor(x, y, z){
this.x = x
this.y = y
this.z = z
this.showX = () => {console.log(this.x)}
}
}
function MixinShowY (SupCls){ // 可以打印y屬性功能的函數,接受一個類型為參數
class Tempcls extends SupCls{
constructor(...args){
super(...args)
this.showY = () => {console.log(this.y)}
}
}
return Tempcls // 返回值為一個類
}
class C extends MixinShowY(A){}
// MixinShowB(A) 的返回值為一個類,可以被C繼承,繼承后同時擁有MixinShowB和A的功能
在MixinShowB函數中,接受一個類作為參數來創建一個新的類型并添加功能showB,任何一個類型都可以被傳入,然后返回新的類型并添加功能。便實現了這個函數功能的復用。
Mixin疊加
上面中z屬性無法被打印,我們可以繼續定義Minix函數添加這個功能
function MixinShowZ (SupCls){ // 增加可以打印y屬性功能的函數,接受一個類型為參數
class Tempcls extends SupCls{
constructor(...args){
super(...args)
this.showZ = () => {console.log(this.Z)}
}
}
return Tempcls // 返回值為一個類
}
class D extends MixinShowY(C){}
// 或者
class D extends MixinShowZ(MixinShowZ(A)){}
obj = new D(1,2,3)
obj.showX()
obj.showY()
上面的兩種寫法效果相同,第二種在A的基礎上連續使用兩次包裝Mixin。獲得了ShowY和ShowZ兩個功能;
此時如果想定義一個類B,他需要在A的基礎上增加ShowZ方法,而不需要ShowY,只需要
class B extends MixinShowZ(A){}
需要哪種功能,就使用該功能對應的Mixin函數混入即可。
裝飾器
裝飾器語法在ES7中的定義,它是一個語法糖,依賴于ES5的Object.defineProperty方法,由于是ES7中的語法,需要使用babel將代碼轉譯為ES5以前的,可以在babel官網在線轉譯少量代碼,也可以在本機上搭建離線的轉譯環境。可以查看博主的JS模塊化管理及babel離線環境搭建
裝飾器,顧名思義就是可以為一個對象添加某種功能的包裝器,在目前JS中只有使用class定義的類才能使用裝飾器
繼續上面的示例,我們為A類添加一個ShowY的功能
function addShowY(cls){ // 裝飾器函數
class Temp extends cls{
constructor(...args){
super(...args)
this.showY = () => {console.log(this.y)}
}
}
return Temp
}
@addShowY // 等價于 A = addshowY(A),裝飾后A標識符已經指向了addShowY的返回值,一個新的類
class A {
constructor(x, y, z){
this.x = x
this.y = y
this.z = z
this.showX = () => {console.log(this.x)}
}
}
a = new A(1,2,3)
a.showY() // 調用成功
任何需要這個功能類,都可以使用這個裝飾器進行裝飾
@addShowY
class B{
constructor(a, b, c, d){
this.a = a
this.b = b
this.c = c
this.d = d
}
}
帶參裝飾器
我們還可以使用帶參數的裝飾器,這需要對象裝飾器函數進行些許的改變,想象一下這個帶參裝飾器函數未來的使用方式應該是下面這樣。
@addname("root") // 為類添加一個family屬性,這個family可以自己指定。等價于C = addname(root)(C)
class C(){} // 這樣C 類將會擁有一個指定的famliy屬性
從用法樂意看出,這個addname函數將會被調用,調用后的返回值是一個接受類的函數,然后返回值為一個類,即
function addname(family){
function func(cls){ //
class Temp extends cls{
constructor(...args){
super(...args)
this.family = family
}
}
return Temp // func()函數調用,返回新的類
}
return func // addname調用后返回一個函數,這個函數執行 func(cls)
}
@addname("root")
class C(){
constructor(x,y){
this.x = x
this.y = y
}
}
let obj = new C(1,2)
console.log(obj.family)
同樣的,這個裝飾器可以用于任何類,并且很久傳入的參數不同,類中被裝飾的屬性值不同,通過這種技術,我們可以將一些通用的功能抽象到一個裝飾器函數中,對需要使用該功能類使用裝飾器注入功能,從而避免了反復的在不同的類中實現相同的代碼,從而然代碼更加簡潔可讀。
總結
以上是生活随笔為你收集整理的JS中的Minix和装饰器实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 16.unix网络编程一卷 unp.h
- 下一篇: 计算器显示e-005什么意思