亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

簡(jiǎn)單了解一下ES6的修飾器

LancerComet / 833人閱讀

摘要:額,經(jīng)歷過上面的知識(shí)了解,應(yīng)該能大概夠理解這段代碼了吧小結(jié)修飾器允許你在類和方法定義的時(shí)候去注釋或者修改它。

閑言

一切都要從公司里的一位老哥給我看的一段代碼說起。。。

@controller("/user")

@auth
@post("/login")
async userLogin = (name, pass) => {
    @required
    // ...
}

以下為對(duì)話:

我:這不是修飾器嗎(因?yàn)橹翱吹竭^@這個(gè)東西)

老哥:還不錯(cuò)嘛,知道是修飾器,那你知道這一段想表達(dá)什么意思嗎

我:這是路由?(一臉懵逼,但是看到了/user和post還有/login,心里想難道這是路由)

老哥:穩(wěn)!

我:震驚了,還能夠這樣寫路由。不行,回去我要好好看看這個(gè)破@

由此開始了修飾器的學(xué)習(xí)~~~
嚶嚶嚶~~

初識(shí)Decorator
首先說明,修飾器在JavaScript中還處于提議階段,目前還不能夠被大部分環(huán)境支持,并且之后還有可能會(huì)改變。如果想要使用該特性請(qǐng)用Babel進(jìn)行轉(zhuǎn)碼或者使用JavaScript的超集TypeScript

在ES6中增加了類的相關(guān)定義和操作(比如class和extends),這樣方便了我們單個(gè)類的操作,但是當(dāng)我們想要在多個(gè)不同類之間共享、復(fù)用一些方法的時(shí)候,會(huì)發(fā)現(xiàn)變得不那么優(yōu)雅,所以decorator被提了出來。

小小的demo:以@作為標(biāo)識(shí)符,既可以作用于類,也可以作用于類屬性

@decorator
class Cat {}

class Dog {
    @decorator
    run() {}
}
修飾器的使用

既然decorator與類相關(guān),我們先了解一下類(這里只是簡(jiǎn)單介紹,想要詳細(xì)了解的,請(qǐng)自行查閱相關(guān)資料,推薦阮一峰的ES6入門)

class Cat {
    constructor(name) {
        this.name = name
    }
    say () {
        console.log("miao ~")
    }
}

這其實(shí)是一個(gè)語(yǔ)法糖,具體的實(shí)現(xiàn)是通過Object.defineProperty()方法來操作的,該方法語(yǔ)法如下:

Object.defineProperty(obj, prop, descriptor)

-> obj: 要在其上定義屬性的對(duì)象
-> prop: 要定義或修改的屬性的名稱
-> descriptor:要被定義或修改的屬性描述符

返回:傳遞給該方法的對(duì)象(即obj)

所以上面那個(gè)Cat的代碼實(shí)際上在執(zhí)行時(shí)是這樣的:

function Cat() {}
Object.defineProperty(Cat.prototype, "say", {
    value: function() {console.log("miao ~")}, // 該屬性對(duì)應(yīng)的值
    enumerable: false, // 為true時(shí),才能夠出現(xiàn)在對(duì)象的枚舉屬性中
    configurable: true, // 為true時(shí),該屬性描述符才能夠被改變
    writable: true // 為true時(shí),value才能被賦值運(yùn)算符改變
}) // 返回Cat.prototype
作用于類的修飾器
function isAnimal(target) { 
    target.isAnimal = true
    return target // 返回的是傳遞給該函數(shù)的對(duì)象
}

@isAnimal
class Cat {
    // ...
}
console.log(Cat.isAnimal) // true

上面的代碼基本等同于:

Cat = isAnimal(function Cat() {})
作用于類屬性的修飾器
function readonly(target, name, descriptor) { 
    descriptor.writable = false
    return descriptor
}

class Cat {
    @readonly 
    say () {
        console.log("miao ~")
    }
}

let kitty = new Cat()
kitty.say = function () {
    console.log("wow ~")
}

kitty.say() // miao ~

通過將descriptor屬性描述符的writable設(shè)置為false,使得say方法只讀,后面對(duì)它進(jìn)行的賦值操作不會(huì)生效,調(diào)用的依舊是之前的方法。

有木有覺得readonly()方法的參數(shù)似曾相識(shí)?它和上文介紹ES6中的類中提到的Object.defineProperty()是一樣的。

其實(shí)修飾器在作用于屬性的時(shí)候,實(shí)際上是通過Object.defineProperty進(jìn)行擴(kuò)展和封裝的。所以上面的代碼實(shí)際上是這樣的:

let descriptor = {
    value: function() {
        console.log("miao ~")
    },
    enumerable: false,
    configurable: true,
    writable: true
}

descriptor = readonly(Cat.prototype, "say", descriptor) || descriptor
Object.defineProperty(Cat.prototype, "say", descriptor)

當(dāng)修飾器作用于類時(shí),我們操作的對(duì)象是類本身,當(dāng)修飾器作用于類屬性時(shí),我們操作的對(duì)象既不是類本身也不是類屬性,而是它的描述符(descriptor)。

當(dāng)然了,你也可以直接在target上進(jìn)行擴(kuò)展和封裝。

function fast(target, name, descriptor) {
    target.speed = 20
    let run = descriptor.value()
    descriptor.value = function() {
        run()
        console.log(`speed ${this.speed}`)
    }
    return descriptor
}

class Rabbit {
    @fast
    run() {
        console.log("running~")
    }
}

let bunny = new Rabbit()

bunny.run() 
// running ~
// speed 20
console.log(bunny.speed) // 20
回到文章開始

讓我們回到文章開始講到的代碼,它怎么閱讀呢

@controller("/api/user")

export class userController {
    @post("/add")
    @required({
        body: ["telephone", "key1"]
    })
    async addUser(ctx, next) {}
    
    @get("/userlist")
    async userList(ctx, next) {}
}

讓我們先看@controller("/api/user")

const symbolPrefix = Symbol("prefix")
export const controller = path => target => (target.prototype[symbolPrefix] = path)

作用是將/api/user作為prefixPath,此時(shí)target為userController {},在該target的原型上設(shè)置path

再接著看@post("/add")

// 以下代碼省略了部分細(xì)節(jié)
...
// export const post = path => (target, name, descriptor) => {}

routerMap.set({
    target: target,
    ...conf
}, target[name]) // name為addUser
for(let [conf, func] of routerMap) {
    // conf為{target, path} 該target為userController {},path為@post()傳遞進(jìn)來的參數(shù)
    let prefixPath = conf.target[symbolPrefix] // 為 /api/user
    let routePath = prefix + path // 為 /api/user/add
}
// 得到了api路徑(routePath),也得到了該api路徑所執(zhí)行的方法(func)
// get同理
...

原理基本上都是類似的,處理修飾器傳遞的參數(shù),得到自己想要的結(jié)果。

額,經(jīng)歷過上面的知識(shí)了解,應(yīng)該能大概夠理解這段代碼了吧~

小結(jié)

修飾器允許你在類和方法定義的時(shí)候去注釋或者修改它。修飾器是一個(gè)作用于函數(shù)的表達(dá)式,它接收三個(gè)參數(shù) target、 name 和 descriptor , 然后可選性的返回被裝飾之后的 descriptor 對(duì)象。

你也可以疊加使用,就像這樣

@post("/add")
@required({
    body: ["telephone", "key1"]
})

async xxx {}
參考:

https://aotu.io/notes/2016/10/24/decorator/index.html

http://taobaofed.org/blog/2015/11/16/es7-decorator/

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/94340.html

相關(guān)文章

  • 工作中常用es6+特性

    摘要:結(jié)合工作中使用情況,簡(jiǎn)單對(duì)進(jìn)行一些復(fù)習(xí)總結(jié),包括常用的語(yǔ)法,等,以及短時(shí)間內(nèi)要上手需要重點(diǎn)學(xué)習(xí)的知識(shí)點(diǎn)不同工作環(huán)境可能有一些差別,主要參考鏈接是阮一峰的博客以及外文博客阮老師大部分文章是直接翻譯的這個(gè)博客簡(jiǎn)介先說一下,是一個(gè)標(biāo)準(zhǔn)化組織,他們 結(jié)合工作中使用情況,簡(jiǎn)單對(duì)es6進(jìn)行一些復(fù)習(xí)總結(jié),包括常用的語(yǔ)法,api等,以及短時(shí)間內(nèi)要上手需要重點(diǎn)學(xué)習(xí)的知識(shí)點(diǎn)(不同工作環(huán)境可能有一些差別),...

    xcold 評(píng)論0 收藏0
  • ES7 Decorators(修飾

    ES6 Decorators(修飾器) 修飾器(Decorator)是一個(gè)函數(shù),用來修改類的行為。這是ES7的一個(gè)提案,目前Babel轉(zhuǎn)碼器已經(jīng)支持 我們?cè)谟螒虼笮晚?xiàng)目種經(jīng)常會(huì)用到的方法,現(xiàn)在es6直接支持 想要使用Decorator的話需要我們配置一下文件夾,配置一下環(huán)境 npm install babel-plugin-transform-decorators-legacy --save-de...

    張漢慶 評(píng)論0 收藏0
  • ES6學(xué)習(xí) 第五章 正則擴(kuò)展

    摘要:前言本章介紹正則的擴(kuò)展。屬性屬性表明正則表達(dá)式帶有標(biāo)志。行終止符所謂行終止符,就是該字符表示一行的終結(jié)。比如,只匹配不在美元符號(hào)后面的數(shù)字,要寫成。前言本章介紹正則的擴(kuò)展。有些不常用的知識(shí)了解即可。本章原文鏈接:正則的擴(kuò)展RegExp 構(gòu)造函數(shù)從 ES6 開始,如果RegExp構(gòu)造函數(shù)第一個(gè)參數(shù)是一個(gè)正則對(duì)象,并且第二個(gè)標(biāo)志存在且為標(biāo)志參數(shù),將不再拋出 TypeError ,將使用這些參數(shù)創(chuàng)...

    番茄西紅柿 評(píng)論0 收藏2637
  • ES6簡(jiǎn)單總結(jié)(搭配簡(jiǎn)單講解和小案例)

    摘要:方法返回一個(gè)布爾值,表示某個(gè)數(shù)組是否包含給定的值,與字符串的方法類似。不可以當(dāng)作構(gòu)造函數(shù),也就是說,不可以使用命令,否則會(huì)拋出一個(gè)錯(cuò)誤。本身是一個(gè)構(gòu)造函數(shù),用來生成數(shù)據(jù)結(jié)構(gòu)。返回一個(gè)布爾值,表示該值是否為的成員。清除所有成員,沒有返回值。 在學(xué)習(xí)es6的過程中,為了方便自己復(fù)習(xí),以及查看,對(duì)api做了一個(gè)極簡(jiǎn)用例介紹。如有錯(cuò)誤多多指正。 一 let和const 1.let (1)一個(gè)大...

    joyqi 評(píng)論0 收藏0
  • ES6學(xué)習(xí)筆記4-Proxy、Reflect、Decorator、Module

    摘要:攔截實(shí)例作為構(gòu)造函數(shù)調(diào)用的操作,比如。方法等同于,這提供了一種不使用,來調(diào)用構(gòu)造函數(shù)的方法。方法對(duì)應(yīng),返回一個(gè)布爾值,表示當(dāng)前對(duì)象是否可擴(kuò)展。這是的一個(gè)提案,目前轉(zhuǎn)碼器已經(jīng)支持。別名或修飾器在控制臺(tái)顯示一條警告,表示該方法將廢除。 Proxy Proxy 這個(gè)詞的原意是代理,用在這里表示由它來代理某些操作,可以譯為代理器,即用自己的定義覆蓋了語(yǔ)言的原始定義。ES6 原生提供 Proxy...

    lushan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<