//不带参数的装饰器
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");