好好爱自己!

typescript 装饰器 decorator

 

 

Decorators are just a clean syntax for wrapping a piece of code with a function

The Journey Begins With Class Decorators

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Families {
  private houses = ["Lannister", "Targaryen"];
 
  get() {
    return this.houses;
  }
  post(request) {
    this.houses.push(request.body);
  }
}
 
class Castles {
  private castles = ["Winterfell", "Casterly Rock"];
 
  get() {
    return this.castles;
  }
  post(request) {
    this.castles.push(request.body);
  }
}

  

1
2
3
4
5
6
7
8
9
10
11
12
13
const httpEndpoints = {};
 
function registerEndpoint(constructor) {
  const className = constructor.name;
  const endpointPath = "/" + className.toLowerCase();
  httpEndpoints[endpointPath] = new constructor();
}
 
registerEndpoint(Families)
registerEndpoint(Castles)
 
console.log(httpEndpoints) // {"/families": Families, "/castles": Castles}
httpEndpoints["/families"].get() // ["Lannister", "Targaryen"]

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const httpEndpoints = {};
 
function registerEndpoint(constructor) {
  const className = constructor.name;
  const endpointPath = "/" + className.toLowerCase();
  httpEndpoints[endpointPath] = new constructor();
}
 
@registerEndpoint
class Families {
  // implementation...
}
 
@registerEndpoint
class Castles {
  // implementation...
}
 
console.log(httpEndpoints) // {"/families": Families, "/castles": Castles}
httpEndpoints["/families"].get() // ["Lannister", "Targaryen"]

  

Unleash the Power of the Method Decorator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const protectedMethods = [];
 
function protect(target, propertyKey, descriptor) {
  const className = target.constructor.name;
  protectedMethods.push(className + "." + propertyKey);
}
 
@registerEndpoint
class Families {
  private houses = ["Lannister", "Targaryen"];
 
  @protect
  get() {
    return this.houses;
  }
   
  @protect
  post(request) {
    this.houses.push(request.body);
  }
}
 
console.log(protectedMethods) // ["Families.get", "Families.post"]

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function nope(target, propertyKey, descriptor) {
  descriptor.value = function() {
    console.log("nope");
  };
  return descriptor;
}
 
@registerEndpoint
class Families {
  private houses = ["Lannister", "Targaryen"];
 
  @nope
  get() {
    return this.houses;
  }
}
 
httpEndpoints["/families"].get() // nope

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function protect(target, propertyKey, descriptor) {
  const originalFunction = descriptor.value;
 
  descriptor.value = function(request) {
    if (request.token !== "123") {
      throw new Error("forbiden!");
    }
    const bindedOriginalFunction = originalFunction.bind(this)
    const result = bindedOriginalFunction(request)
    return result
  };
 
  return descriptor;
}
 
@registerEndpoint
class Families {
  private houses = ["Lannister", "Targaryen"];
 
  @protect
  get() {
    return this.houses;
  }
}
 
httpEndpoints["/families"].get({token: "123"}) // ["Lannister", "Targaryen"]
httpEndpoints["/families"].get({}) // Uncaught Error: forbiden!

  

Gain More Power With Decorator Factories

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const httpEndpoints = {};
 
function registerEndpoint(constructor) {
  const className = constructor.name;
  const endpointPath = "/" + className.toLowerCase();
  httpEndpoints[endpointPath] = new constructor();
}
 
@registerEndpoint
class Families {
  // implementation...
}
 
@registerEndpoint
class Castles {
  // implementation...
}
 
console.log(httpEndpoints) // {"/families": Families, "/castles": Castles}
httpEndpoints["/families"].get() // ["Lannister", "Targaryen"]

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const httpEndpoints = {};
 
function registerEndpointFactory(endpointPath) {
  return function registerEndpoint(constructor) {
    httpEndpoints[endpointPath] = new constructor();
  }
}
 
@registerEndpointFactory("/families/stark/members")
class StarkMembers {
  private members = ["Robb", "Sansa", "Arya"];
 
  get() {
    return this.members;
  }
 
  @protect
  post(request) {
    this.members.push(request.body);
  }
}
 
console.log(httpEndpoints) // {"/families/stark/members": StarkMembers}
httpEndpoints["/families/stark/members"].get() // ["Robb", "Sansa", "Arya"]

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function protect(token) {
  return function(target, propertyKey, descriptor) {
    const originalFunction = descriptor.value;
 
    descriptor.value = function(request) {
      if (request.token !== token) {
        throw new Error("forbiden!");
      }
      const bindedOriginalFunction = originalFunction.bind(this);
      const result = bindedOriginalFunction(request);
      return result;
    };
 
    return descriptor;
  };
}
 
class StarkMembers {
  private members = ["Robb", "Sansa", "Arya"];
 
  @protect("abc")
  post(request) {
    this.members.push(request.body);
  }
}

  

Conclusion

 

yay, you did it!

posted @   立志做一个好的程序员  阅读(178)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
历史上的今天:
2016-09-25 javascript 中的this
2016-09-25 javascript 中 function bind()

不断学习创作,与自己快乐相处

点击右上角即可分享
微信分享提示