装饰器 — 装饰器修饰类
最后更新于: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)
';