国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > JS > 正文

一文讀懂ES7中的javascript修飾器

2024-05-06 16:50:32
字體:
供稿:網(wǎng)友

什么是修飾器

修飾器(Decorator)是javascript/339279.html">ES7的一個(gè)提案,它的出現(xiàn)能解決兩個(gè)問題:

  • 不同類間共享方法
  • 編譯期對類和方法的行為進(jìn)行改變

用法也很簡單,就是在類或方法的上面加一個(gè)@符,在vue in typescript中經(jīng)常用到

ES7,javascript,修飾器

以上的兩個(gè)用處可能不太明白,沒關(guān)系,我們開始第一個(gè)例子

例子1:修飾類

@setPropclass User {}function setProp(target) { target.age = 30}console.log(User.age)

這個(gè)例子要表達(dá)的是對User類使用setProp這個(gè)方法進(jìn)行修飾,用來增加User類中age的屬性,setProp方法會(huì)接收3個(gè)參數(shù),我們現(xiàn)在接觸第一個(gè),target代表User類本身。

例子2:修飾類(自定義參數(shù)值)

@setProp(20)class User {}function setProp(value) { return function (target) {  target.age = value }}console.log(User.age)

此例和上面功能基本一致,唯一差別在于值是參考修飾函數(shù)傳過來的

例子2:修飾方法

class User { @readonly getName() {  return 'Hello World' }}// readonly修飾函數(shù),對方法進(jìn)行只讀操作function readonly(target, name, descriptor) { descriptor.writable = false return descriptor}let u = new User()// 嘗試修改函數(shù),在控制臺(tái)會(huì)報(bào)錯(cuò)u.getName = () => { return 'I will override'}

上例中,我們對User類中的getName方法使用readonly修飾器進(jìn)行修飾,使得方法不能被修改。第一個(gè)參數(shù)我們已經(jīng)知道了,參數(shù)name為方法名,也就是readonly,參數(shù)descriptor是個(gè)啥東西呢,看到這行descriptor.writable = false,我們大家猜的也差不多了,這三個(gè)參數(shù)對應(yīng)的就是Object.defineProperty的三個(gè)參數(shù),我們來看一下:

ES7,javascript,修飾器

我們設(shè)置descriptor.writable = false就是讓函數(shù)不可以被修改,如果我們寫成

descriptor.value = 'function (){ console.log('Hello decorator') }'

那么,輸出就是Hello World了,而是Hello decorator,是不是已經(jīng)意識到修飾器的好處了。現(xiàn)在我們來看看實(shí)際工作中,我們用到修飾器的例子

實(shí)際應(yīng)用1:日志管理

在用webpack打包時(shí),我們經(jīng)常需要好多步驟,比如第一步讀取package.json文件,第二步處理該文件,第三步加載webpack.base.js文件,第四步進(jìn)行打包...為了直觀,我們經(jīng)常在每一步打印一些日志文件,比如這步都干了些什么事,很明顯打印日志的操作和業(yè)務(wù)代碼根本就一點(diǎn)關(guān)系沒有,我們不應(yīng)該把日志和業(yè)務(wù)摻和在一起,這樣使用修飾器就是避免這個(gè)問題,以下為代碼:

class Pack { @log('讀取package.json文件') step1() {  // do something...  // 沒有修飾器之前,我們通常把console.log放到這里寫  // 放到函數(shù)里面寫會(huì)有兩個(gè)壞處  //  1.console和業(yè)務(wù)無關(guān),會(huì)破壞函數(shù)單一性原則  //  2.如果要?jiǎng)h除所有的console,那我們只能深入到每一個(gè)方法中 } @log('合并webpack配置文件') step2() {  // do something... }}function log(value) { return function (target, name, descriptor) {  // 在這里,我們還可以拿到函數(shù)的參數(shù),打印更加詳細(xì)的信息  console.log(value) }}let pack = new Pack()pack.step1()pack.step2()

實(shí)際應(yīng)用2:檢查登錄

這個(gè)例子在實(shí)際的開發(fā)中常用得到,我們一些操作前,必須得判斷用戶是否登錄,比較點(diǎn)贊、結(jié)算、發(fā)送彈幕...按照之前的寫法,我們必須在每一個(gè)方法中判斷用戶的登錄情況,然后再進(jìn)行業(yè)務(wù)的操作,很顯然前置條件和業(yè)務(wù)又混到了一起,用修飾器,就可以完美的解決這一問題,代碼如下:

class User { // 獲取已登錄用戶的用戶信息 @checkLogin getUserInfo() {  /**   * 之前,我們都會(huì)這么寫:   *  if(checkLogin()) {   *   // 業(yè)務(wù)代碼   *  }   * 這段代碼會(huì)在每一個(gè)需要登錄的方法中執(zhí)行   * 還是上面的問題,執(zhí)行的前提和業(yè)務(wù)又混到了一起   */  console.log('獲取已登錄用戶的用戶信息') } // 發(fā)送消息 @checkLogin sendMsg() {  console.log('發(fā)送消息') }}// 檢查用戶是否登錄,如果沒有登錄,就跳轉(zhuǎn)到登錄頁面function checkLogin(target, name, descriptor) { let method = descriptor.value // 模擬判斷條件 let isLogin = true descriptor.value = function (...args) {  if (isLogin) {   method.apply(this, args)  } else {   console.log('沒有登錄,即將跳轉(zhuǎn)到登錄頁面...')  } }}let u = new User()u.getUserInfo()u.sendMsg()

結(jié)語

以上只是修飾器的基本應(yīng)用,只要我們掌握了原理,在實(shí)際的工作中,要思考自己的應(yīng)用場景,只要我們涉及需要在執(zhí)行前做一些處理的應(yīng)用,不管是修改函數(shù)的參數(shù)值,還是增加屬性,還是執(zhí)行的先決條件,我們都可以使用修飾器,這種編程的方式,就是面向切面編程

源碼以及使用方法,請移步GitHub

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對VeVb武林網(wǎng)的支持。


注:相關(guān)教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 利川市| 镇原县| 栖霞市| 胶南市| 张家川| 汤原县| 晋城| 久治县| 贵定县| 尉氏县| 镶黄旗| 大竹县| 汾西县| 延津县| 蒲城县| 鄄城县| 怀集县| 合川市| 施甸县| 镇安县| 琼结县| 雷山县| 邛崃市| 鲁山县| 云霄县| 山阴县| 乐陵市| 鄯善县| 溆浦县| 克拉玛依市| 正蓝旗| 泉州市| 中山市| 镇原县| 耿马| 宜君县| 长宁县| 隆安县| 万载县| 揭东县| 化德县|