//不帶參數的裝飾器 function logClass(target: any) { var original = target; function construct(constructor, args) { var c: any = function () { return constructor.apply(this.args); } c.prototype = constructor.prototype; return new c(); } var f: any = function (...args) { console.log("New:" + original.name); return construct(original, args); } f.prototype = original.prototype; return f; } //類裝飾器,帶有參數的 function logClass2(option:string) { return function (target: any) { console.log("option:"+option); var original = target; function construct(constructor, args) { var c: any = function () { return constructor.apply(this.args); } c.prototype = constructor.prototype; return new c(); } var f: any = function (...args) { console.log("New:" + original.name); return construct(original, args); } f.prototype = original.prototype; return f; } } //方法裝飾器 function logMethod(target: any, key: string, descriptor: any) { var originalMethod = descriptor.value;//保留原方法的引用 descriptor.value = function (...args: any[]) { var a = args.map(a => JSON.stringify(a)).join();//將方法參數轉爲字符串 var result = originalMethod.apply(this, args);//執行方法,獲得其返回值 var r = JSON.stringify(result);//將返回值轉爲字符串 console.log(`Call:${key}(${a}) => ${r}`); return result; } return descriptor;//返回編輯後的屬性描述對象 } //屬性裝飾器 function logProperty(target: any,key:string) { var _val = this[key];//屬性值 var getter = function () { console.log(`Get:${key} => ${_val}`); return _val; } var setter = function (newVal) { console.log(`Set:${key} => ${newVal}`); _val = newVal; } //刪除屬性,在嚴格模式下,若是對象是不可配置的,將會拋出一個錯誤。不然返回false if (delete this[key]) { Object.defineProperty(target, key, { get: getter, set: setter, enumerable: true, configurable:true }) } } //參數裝飾器 function addMetadata(target: any, key: string, index: number){ var metadataKey = `_log_${key}_parameters`; if (Array.isArray(target[metadataKey])) { target[metadataKey].push(index); } else { target[metadataKey] = [index]; } } //讀取經過參數裝飾器添加的元數據,在執行時,不在展現全部參數,而是僅打印被裝飾的參數 function readMetadata(target: any, key: string, descriptor: any) { var originMethod = descriptor.value; descriptor.value = function (...args: any[]) { var metadataKey = `_log_${key}_parameters`; var indices = target[metadataKey]; if (Array.isArray(indices)) { for (var i = 0; i < args.length; i++){ if (indices.indexOf(i) !== -1) { var arg = args[i]; var argStr = JSON.stringify(arg) || arg.toString(); console.log(`${key} arg[${i}]:${argStr}`); } } var result = originMethod.apply(this, args); return result; } return descriptor; } } @logClass @logClass2("option value") class Person { public name: string; @logProperty public surname: string; constructor(name: string, surname: string){ this.name = name; this.surname = surname; } @readMetadata @logMethod say(@addMetadata st:string):string { console.log(this.name + "-->" + this.surname + " says :"+st); return this.name + "-->" + this.surname + " says :"+st; } } var me = new Person("raa", "jan"); me.surname = "hello1"; var n = me.surname; me.say("hello");