装饰器 — 装饰器修饰类

最后更新于:2022-04-02 08:10:33

[TOC] >[success] # 装饰器装饰在 --- 类 ~~~ 1.参数 当前被修饰的类 ~~~ >[danger] ##### @+'函数名' 使用方式 -- 给类加自定义的静态属性或者静态方法 ~~~ 1.可以给装饰的类添加'静态方法' ~~~ ~~~ function setAge(target){ target.age = '17' } @setAge class MyPerson{} console.log(MyPerson.age) // 17 ~~~ >[danger] ##### 推论类装饰器,函数中参数target指向 ~~~ 1.根据上面的案例,可以发现装饰器函数有一个参数,这个'参数target' 指向是谁?如果根据现有的现象,跟参数'traget'增加了一个age属性,这个 属性最后成为了类'MyPerson' 的静态属性,推论出'target'很有可能指向 当前类 2.下面将通过代码进行验证是否符合我们的想法,验证代码的思路用一个 变量来接受'target',利用这个变量在和'MyPerson' 去比较 ~~~ * 验证代码 ~~~ let targetType = null function setAge(target){ targetType = target target.age = '17' } @setAge class MyPerson{} console.log(targetType === MyPerson) // true console.log(targetType === MyPerson.prototype.constructor) // true ~~~ >[danger] ##### @+'函数' 使用工厂方式 -- 给类加自定义的静态属性或者静态方法 ~~~ 1.这个使用返回的内容页必须是一个函数 2.这样就可以给装饰器进行传参 ~~~ ~~~ function setAge(number){ return (target)=>{ target.age = 17+number } } @setAge(3) class MyPerson{} console.log(MyPerson.age) // 20 ~~~ >[danger] ##### 通过装饰器给实例添加--属性和方法 ~~~ 1.首先我们要给实例添加属性或者一些方法,肯定是要通过原型链'prototype'的形式 ,有因此修饰类的装饰器中的参数执行的正好是类本身,因此只要给这个参数的原型 链上添加属性和方法就可以实现给实例添加 ~~~ ~~~ function setAge(number){ return (target)=>{ target.prototype.age = 17 } } @setAge(3) class MyPerson{} const myPerson = new MyPerson() console.log(myPerson.age) // 17 ~~~ >[danger] ##### 阮一峰老师文章中的利用装饰混入多个属性案例 ~~~javascript // mixins.js export function mixins(...list) { return function (target) { Object.assign(target.prototype, ...list) } } // main.js import { mixins } from './mixins' const Foo = { foo() { console.log('foo') } }; @mixins(Foo) class MyClass {} let obj = new MyClass(); obj.foo() // 'foo' ~~~ 上面代码通过修饰器`mixins`,把`Foo`对象的方法添加到了`MyClass`的实例上面。可以用`Object.assign()`模拟这个功能。 ~~~javascript const Foo = { foo() { console.log('foo') } }; class MyClass {} Object.assign(MyClass.prototype, Foo); let obj = new MyClass(); obj.foo() // 'foo' ~~~ >[danger] ##### 用class 装饰class ~~~ 1.目前发现的已知问题,方法会执行两次并且装饰器中的为准 2.最后'MyPerson' 被替换成了装饰器返回的class,即变相继承, 也就是装饰器返回的类替换了被装饰的类 ~~~ ~~~ function setAge(target){ return class extends target { constructor(){ super() this.name = '1' this.age = 2 } speak(){ console.log('好酷') } toDo(){ console.log('唱跳rap') } } } @setAge class MyPerson{ constructor(){ this.sex= '男' } speak1(){ console.log('我好酷') } } const myPerson = new MyPerson() console.log(myPerson.age) console.log(myPerson.name) console.log(myPerson.sex) console.log(myPerson.speak()) console.log(myPerson.toDo()) console.log(myPerson.speak1()) ~~~ * 打印结果 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/8b5134a6c6de5ea12b779b11a60eae84_558x191.png) >[danger] ##### 根据上面的案例反推,如果装饰器中的返回类没有继承被装饰类 ~~~ 1.只能使用装饰器中返回类的属性和方法,不能使用被装饰器的属性和方法 2.但和上面有一样的问题方法会被执行两次不知道是不是因为'babelrc'的bug ~~~ ~~~ function setAge(target){ return class { constructor(){ this.name = '1' this.age = 2 } speak(){ console.log('好酷') } toDo(){ console.log('唱跳rap') } } } @setAge class MyPerson{ constructor(){ this.sex= '男' } speak1(){ console.log('我好酷') } } const myPerson = new MyPerson() console.log(myPerson.age) console.log(myPerson.name) console.log(myPerson.speak()) console.log(myPerson.toDo()) ~~~ * 打印结果 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/0e84e786e6ece0b2094b84a14d48a740_429x121.png)
';