聊聊es7的decorator修飾器

Decorator是一個(gè)函數(shù)谷誓,用來修改類或者類的屬性的行為窜护。
說的直白點(diǎn)decorator就是給類添加或者修改類的變量與方法的。
先看一個(gè)例子

@addCxh
class DaBao {}
function addCxh(target){
    target.cxh = "first"
}
console.log(DaBao.cxh);

在執(zhí)行以前先:npm install --save-dev babel-plugin-transform-decorators-legacy
安裝一個(gè)支持decorator的插件。
然后babel --plugins transform-decorators-legacy decorator.js --out-file d.js
拿到轉(zhuǎn)碼好的d.js后我們得到的代碼如下:

"use strict";

var _class;

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var DaBao = addCxh(_class = function DaBao() {
    _classCallCheck(this, DaBao);
}) || _class;

function addCxh(target) {
    target.cxh = "first";
}
console.log(DaBao.cxh);

當(dāng)然矗愧,執(zhí)行的結(jié)果肯定是 first。
那么我們分析下這段代碼郑原。在class之前加上@addCxh以后其實(shí)就相當(dāng)于對(duì)DaBao作為參數(shù)執(zhí)行了addCxh 然后 || class DaBao本身,
即DaBao = addCxh(DaBao) || DaBao;
而addCxh相當(dāng)于給DaBao添加了一個(gè)靜態(tài)變量唉韭。target即修飾的目標(biāo)類。

如果我們需要給一個(gè)類添加一個(gè)靜態(tài)方法犯犁,但是這個(gè)方法并不固定属愤,我們需要封裝兩個(gè)變量進(jìn)去,一個(gè)是target酸役,代表類本身住诸,另一個(gè)代表是我們需要的方法。則:

function setClass(a){
    if(a == '1'){
        return (value) => {
            console.log(value)
        }
    }
    return () => {
        console.log(1)
    }
    
}

@addCxh(setClass(1))
class DaBao {}

@addCxh(setClass(2))
class XiaoBao{}

function addCxh(addFun){
    return (target) => {
        target.cxh = addFun;
    }
}
DaBao.cxh(2);
XiaoBao.cxh()

結(jié)果如下:

Paste_Image.png

addCxh接受一個(gè)變量作為參數(shù)涣澡,給目標(biāo)類添加靜態(tài)方法或變量贱呐。
setClass返回不同的函數(shù)傳遞給addCxh,然后在給目標(biāo)類添加該方法。
添加實(shí)例屬性

@addCxh('first')
class DaBao {}
function addCxh(data){
    return (target) => {
        target.prototype.cxh = data;
    }
}
var dabao = new DaBao;
console.log(dabao.cxh);

結(jié)果: first暑塑;
配合assign添加多個(gè)屬性
新建一個(gè)addDabao.js

export default function(...list) {
    return  (target) => {
        Object.assign(target.prototype,...list)  //合并
    }
} 

decorator.js

import addDabao from './addDabao1';

const obj =  {
    sex : 1,
    addName(){
        this.name = 'cxh'
    },
    setAge(n){
        this.age = n;
    }
}

@addDabao(obj)
class DaBao {}

var dabao = new DaBao;
console.log(dabao.sex);
dabao.setAge(24)
console.log(dabao.age);
dabao.addName()
console.log(dabao.name);

結(jié)果:


Paste_Image.png

上面這段代碼將obj的屬性添加到了 class DaBao中吼句,這叫做混入模式 --mixin

修飾類的變量與方法

class Dabao {
    @setAttr
    cxh(){
        return true
    } 
}
function setAttr(targt, name, decorator) {
    decorator.writable = false
    return 
}

var dabao = new Dabao;
console.log(dabao.cxh)
dabao.cxh = () => {
    return false
}
console.log(dabao.cxh)

結(jié)果:

Paste_Image.png

上面的代碼中setAttr方法三個(gè)參數(shù)分別代表,操作對(duì)象事格,屬性名稱惕艳,屬性參數(shù)

多個(gè)修飾器修飾一個(gè)方法 以及執(zhí)行順序

function set(b){
    console.log(b)
    return (target, property, de) => {
        de.writable = b
        console.log(b)
        return de
    };
}

class Dabao {
    @set(false)
    @set(true)
    method(){}
}
var dabao = new Dabao;
dabao.method = () => {console.log(1)}

結(jié)果:

Paste_Image.png

最終method方法的writable的值為 false,兩個(gè)修飾器的執(zhí)行順序依次執(zhí)行set方法,然后在倒敘返回驹愚,先返回第二個(gè)远搪,再返回第一個(gè)。
Trait
Trait的功能有很多逢捺,防止同名方法的沖突谁鳍、排除混入某些方法、為混入的方法起別名等等。我們可以使用第三方模塊traits-decorator

import { traits } from 'traits-decorator';
import { traits } from 'traits-decorator';
class Dabao {
  big() { console.log('dabao123') }
}
const Xiaobao= {
  big() { console.log('dabao123') },
  small() { console.log('xiaobao') }
};

@traits(Dabao , Xiaobao)
class Cxh{ }

則會(huì)報(bào)錯(cuò)倘潜;但是我們改成:

import { traits , excludes } from 'traits-decorator';
class Dabao {
  big() { console.log('dabao123') }
}
const Xiaobao= {
  big() { console.log('dabao123') },
  small() { console.log('xiaobao') }
};

@traits(Dabao , Xiaobao::excludes ('big'))
class Cxh{ }

excludes ('big')排除big方法绷柒。
當(dāng)然我們也可以給函數(shù)起一個(gè)其他的名字

import { traits , alias} from 'traits-decorator';
class Dabao {
  big() { console.log('dabao123') }
}
const Xiaobao= {
  big() { console.log('dabao123') },
  small() { console.log('xiaobao') }
};

@traits(Dabao , Xiaobao::alias({big:'sobig'}))
class Cxh{ }

alias({big:'sobig'})將函數(shù)名改成sobig傳入。

2017年8月13日

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末涮因,一起剝皮案震驚了整個(gè)濱河市废睦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌养泡,老刑警劉巖嗜湃,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異澜掩,居然都是意外死亡购披,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門肩榕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刚陡,“玉大人,你說我怎么就攤上這事株汉¢佘” “怎么了?”我有些...
    開封第一講書人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵郎逃,是天一觀的道長(zhǎng)哥童。 經(jīng)常有香客問我,道長(zhǎng)褒翰,這世上最難降的妖魔是什么贮懈? 我笑而不...
    開封第一講書人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮优训,結(jié)果婚禮上朵你,老公的妹妹穿的比我還像新娘。我一直安慰自己揣非,他們只是感情好抡医,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著早敬,像睡著了一般忌傻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上搞监,一...
    開封第一講書人閱讀 51,274評(píng)論 1 300
  • 那天水孩,我揣著相機(jī)與錄音,去河邊找鬼琐驴。 笑死俘种,一個(gè)胖子當(dāng)著我的面吹牛秤标,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播宙刘,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼苍姜,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了悬包?” 一聲冷哼從身側(cè)響起怖现,我...
    開封第一講書人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎玉罐,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體潘拨,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吊输,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了铁追。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片季蚂。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖琅束,靈堂內(nèi)的尸體忽然破棺而出扭屁,到底是詐尸還是另有隱情,我是刑警寧澤涩禀,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布料滥,位于F島的核電站,受9級(jí)特大地震影響艾船,放射性物質(zhì)發(fā)生泄漏葵腹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一屿岂、第九天 我趴在偏房一處隱蔽的房頂上張望践宴。 院中可真熱鬧,春花似錦爷怀、人聲如沸阻肩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽烤惊。三九已至,卻和暖如春吁朦,著一層夾襖步出監(jiān)牢的瞬間撕氧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工喇完, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留伦泥,地道東北人剥啤。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像不脯,于是被迫代替她去往敵國(guó)和親府怯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容