ES7(ES2016)中的Decorator

Decorator,字面意思是修飾器。用來修飾啥呢? 。先看一段代碼index.js

let readOnly = function(target, name, descriptor){
    descriptor.writable=false;
    return descriptor
}

class ClassA {
    @readOnly
    boo() {
        console.log('can not writable');
    }
}

let a = new ClassA();
console.log(a.boo());
a.boo = function(){
    console.log('new foo');
}; // 
console.log(a.boo());

PS:上面代碼的運行需要babel。

安裝babel

npm install babel-cli -g 
npm install babel-plugin-transform-decorators-legacy --save-dev

在程序根目錄下創建文件.babelrc,內容如下

{
  "plugins": ["transform-decorators-legacy"]
}

然後將babel代碼轉換成普通的ES5代碼:

babel --optional es7.decorators index.js > index.es5.js

執行index.es5.js

// can not writable

並沒有看到修改後的foo輸出new foo

裝飾者模式

在不改變原有對象基礎上,豐富原對象的功能。

function A(){
    this.name = 'A';
}
A.prototype.say=function(){console.log(this.name)}

var say1 = A.prototype.say;

A.prototype.say=function(){
    say1.call(this);
    console.log("I am new say fn ");
}
var a = new A();
a.say();

裝飾者模式的一個應用場景有哪些?
面向切面編程 Aspect Oriented Programming(AOP)

下面的例子中一個前置裝飾,一個後置裝飾。

Function.prototype.before=function(beforeFn){
    var that = this;
    return function(){
        beforeFn.apply(this, arguments);
        return that.apply(this, arguments);
    }
}
Function.prototype.after=function(afterFn){
    var that = this;
    return function(){
        var result = that.apply(this, arguments);
        afterFn.apply(this, arguments);
        return result;
    }
}
function foobar(x, y){
    console.log(x, y)
}

function foo(x, y){
    console.log(x/10, y/10);
}

function bar(x, y){
    console.log(x*10, y*10);
}

foobar = foobar.before(foo).after(bar);

foobar(2,3);
// 0.2 0.3
// 2 3
// 20 30

Decorator與日誌系統

const http = require('http');

function log(target, name, descriptor) {
    var oldValue = descriptor.value;

    descriptor.value = function (req, res) {
        console.log(`${req.method} ${req.url}`)
        return oldValue.apply(null, arguments);
    };

    return descriptor;
}

class Router {
    @log
    router(req, res){
        res.end('okay');
    }
}
const server = http.createServer((req, res) => {
    (new Router()).router(req, res);
});

server.listen(3000, ()=>{
    console.log('server has started......')
});

這個日誌系統簡單的記錄訪問路徑(Method + URL);

AOP的應用場景相對而言,還是比較廣泛的。日誌系統、安全控制/訪問控制、性能監測以及緩存等,這些都是AOP的典型應用場景。

【參考資料】

ES7 Decorator 裝飾者模式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章