您的位置:首页 > Web前端 > JavaScript

装饰器在js中的实现原理

2020-02-06 06:26 120 查看

  在项目中总是能看到@connect、@Debounce、@巴拉巴拉!通过百度才知道它叫做装饰器。

装饰器有什么好?

比如说:当我们写好了一个组件它叫做纯洁,当时在创造它的时候我们只想让它做一件事,但是突然有人告诉你我要加一个功能,可是我又不想让我的纯洁变得不纯洁,这时候就可以用装饰器把新增的功能借给我的纯洁。(可直接略过熊哥讲的pthon)

为什么就能借呢?

首先要用一个合适的颜色介绍教我用装饰器的人,熊哥,介绍完毕!
熊哥说:豪杰啊,python你看不懂啊!(我说扯犊子)
熊哥说:不信你看啊 ~~~~~~

def a(a_func):
def b():
print('111')
a_fun()
print('333')
return b
def c():
print('222')
c=a(c)
c()//这里输出111,222,333

熊哥说:(。。。省略一万字)!
总结一下就是,当我们希望让c也能输出111和333的时候我们就运用闭包的方式将c传到函数a中,在把a的返回值重新赋值给变量c这样函数c被变量c覆盖后就可以输出111,222,333啦!
也就是这个原理,我们便可以使用这个语法糖!下面是语法糖写法!

def a(a_func):
def b():
print('111')
a_fun()
print('333')
return b
@a
def c():
print('222')

通过熊哥的引导,我慢慢有个理解了,但是!我用js的啊,进入正题!


分割线--------------------------------------------------------------------------------------------------

在JS中装饰器的原理

由于原生需要配置很多,现在还没有完全搞明白,哈哈哈哈哈哈哈哈,就直接在现成的框架中举例子啦!
在现在我用的antd-pro这个框架中我们可以直接使用装饰器模式,话不说上栗子!

const miao= (target)=>{
target.miao = 'miao';
return target
}
@miao
class Tom{

}
console.log("怎么叫=>",Tom.miao)//很明显这里输出miao

其实单从这个栗子就能看出来,我们的Tom是怎么借方法去使用的,不就是从把Tom传给了miao这个方法,然后给Tom了一个属性从而让Tom知道自己怎么叫。但是! 为什么我写了个@就能把Tom放进去了呢???

终于等到你,我的 Object.defineProperty()!

此处有复习Object.defineProperty()
其实这个语法糖,本质就是构造函数,python用的闭包,js用的就是Object.defineProperty。上代码!!!

class Tom{

}

Object.defineProperty(Tom, "miao", {
value: 'miao',
enumerable: false,
configurable: true,
writable: true
});

那么我对一个类的某一个属性使用装饰器呢

function readonly(target, name, descriptor) {
discriptor.writable = false;
return discriptor;
}
class Tom{
@readonly
say() {
console.log("miao");
}
}
let tom= new Tom();
tom.say = function() {
console.log("wang");
}
tom.say()

上述代码,当我想要让Tom学狗叫,但是实际结果却是Tom不能学,并且报了一个错误!仔细看了一下这个readonly,这个readonly和Object.defineProperty长得好像啊!
原来啊:在装饰器模式下,当我们想要装饰一个属性的时候,实际上是通过 Object.defineProperty 来对原有的descriptor进行封装。

descriptor:

  • configurable控制是不是能删、能修改descriptor本身。
  • writable控制是不是能修改值。
  • enumerable控制是不是能枚举出属性。
  • value控制对应的值,方法只是一个value是函数的属性。
  • get和set控制访问的读和写逻辑。

这不就是Object.defineProperty 所做的操作吗!所以说实现的过程如下代码所示:

let descriptor = {
value: function() {
console.log("miao");
},
enumerable: false,
configurable: true,
writable: true
};
descriptor = readonly(Tom, "say", descriptor) || descriptor;
Object.defineProperty(Tom, "say", descriptor);

这个栗子是为了说明如何装饰已有的属性是否可写,当然如果只是会用是不够滴,多多看一下封装好的方法了解原理,尝试使用装饰器的方式去使用这些方法!

结束!

  • 点赞
  • 收藏
  • 分享
  • 文章举报
老实的豪杰 发布了3 篇原创文章 · 获赞 0 · 访问量 44 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: