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