恰好最近在弄 TypeScript ,不少用到裝飾器 因此就從基礎開始看起.javascript
class Decoration { constructor() { this.keyValue = "" } @statement // 裝飾器命名 url = 'aaa'; //被裝飾的屬性 agent() { console.log( this.url,'-------------' ,this.keyValue); } } function statement(proto, key, descriptor){ console.log('sdsdsd',proto, key, descriptor); descriptor.writable = false; //被裝飾屬性不可寫 } 複製代碼
class Decoration { constructor() { this.value = "" } @statement // 裝飾器命名 url = 'sjh'; //被裝飾的屬性 agent() { console.log( this.url,'+++' ,this.value); } } function statement(proto, key, descriptor) { console.log('sdsdsd',proto, key, descriptor); descriptor.writable = true // console.log(descriptor.initializer()) //被裝飾的屬性值;裝飾私有屬性特有的一個屬性 descriptor.initializer = function () { return 'url的值被修改了' } } var os = new Decoration(); console.log(os.agent()); // 解析 輸出 {constructor: ƒ, agent: ƒ} url {configurable: true, enumerable: true, writable: true, initializer: ƒ} url的值被修改了 ------ undefined statement裝飾器做用於 url 咱們定義的function statement有個 initializer方法 將值作了修改 initializer 由babel內部是用來建立對象屬性的屬性描述符 複製代碼
class Decoration { constructor() { this.value = ""; } url='1' @pro //裝飾原型方法 agent() { console.log(this.url + "++" + this.value); } } function pro(proto, key, descriptor){ console.log(proto, key, descriptor)//打印結果以下; let oldValue = descriptor.value //被裝飾的函數 descriptor.value = function(){ console.log('被裝飾的函數重寫') } } var os = new Decoration(); os.agent() 輸出: {constructor: ƒ, agent: ƒ} "agent" {value: ƒ, writable: true, enumerable: false, configurable: true} 被裝飾的函數重寫 複製代碼
class Decoration { constructor() { this.value = ""; } @skin agent() { console.log(this.value + "----------" + this.age); } } function skin(traget) { traget.age = '18' //添加一個屬性age並賦值18 } var os = new Decoration(); os.agent(); 輸出 this.age 複製代碼
class C { constructor(){ this.children ='1' } @enumerable(false) get method() { return this.children.length; } } function enumerable(value) { return function (target, key, descriptor) { descriptor.enumerable = value; return descriptor; } } var c = new C(); c.method(); 複製代碼
class Person { @memoize get name() { return `${this.first} ${this.last}` } set name(val) { let [first, last] = val.split(' '); this.first = first; this.last = last; } } let memoized = new WeakMap(); function memoize(target, name, descriptor) { let getter = descriptor.get, setter = descriptor.set; descriptor.get = function() { let table = memoizationFor(this); if (name in table) { return table[name]; } return table[name] = getter.call(this); } descriptor.set = function(val) { let table = memoizationFor(this); setter.call(this, val); table[name] = val; } } function memoizationFor(obj) { let table = memoized.get(obj); if (!table) { table = Object.create(null); memoized.set(obj, table); } return table; } 複製代碼
裝飾是一種特殊種類的聲明可被做用於一個類聲明、方法、訪問器,屬性或參數。其用法與 ES7 無太大差異。 function f() { console.log("f(): evaluated"); return function (target, propertyKey: string, descriptor: PropertyDescriptor) { console.log("f(): called"); } } function g() { console.log("g(): evaluated"); return function (target, propertyKey: string, descriptor: PropertyDescriptor) { console.log("g(): called"); } } class C { @f() @g() method() {} } 複製代碼
注意TypeScript不容許爲單個成員裝飾get和set訪問器。相反,成員的全部裝飾器必須應用於以文檔順序指定的第一個訪問器。這是由於裝飾器適用於屬性描述符,該屬性描述符組合了訪問器get和set訪問器,而不是單獨的每一個聲明。java
class Point { private _x: number; private _y: number; constructor(x: number, y: number) { this._x = x; this._y = y; } @configurable(false) get x() { return this._x; } @configurable(false) get y() { return this._y; } } function configurable(value: boolean) { return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { descriptor.configurable = value; }; } 複製代碼
var counter = 0; var add = function() { counter++; }; @add function foo() {} 複製代碼
歡迎關注微信公衆號!,進行更好的交流。
複製代碼