装饰器在js中的实现原理
在项目中总是能看到@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);
这个栗子是为了说明如何装饰已有的属性是否可写,当然如果只是会用是不够滴,多多看一下封装好的方法了解原理,尝试使用装饰器的方式去使用这些方法!
结束!
- 点赞
- 收藏
- 分享
- 文章举报
- 纯js 图片异步加载原理及实现
- 使用requireJS加载不符合AMD规范的js文件:shim的使用方式和实现原理
- 深入理解vue.js双向绑定的实现原理
- js自定义鼠标右键的实现原理及源码
- js实现幻灯片轮播原理
- JS滑动下划线导航菜单实现原理
- 模拟 co.js 的实现原理 (koa中间件的实现)
- js中自定义标签(TagLib)原理与实现
- js版本的文本文件文件保存编码自动检测功能实现与检测原理
- 深入理解vue.js双向绑定的实现原理
- js模块开发(同步模块)实现原理
- React.js核心原理实现:首次渲染机制
- Android JSBridge的原理与实现 (prompt和javascript)
- js实现图片上传预览原理分析
- 微信域名检测接口原理,微信js域名检测接口该如何实现
- js树型菜单的实现原理
- 纯js实现遮罩层效果原理分析
- 网站JS源码1--产品分类下拉菜单实现原理
- 【JS】304- KOA2框架原理解析和实现
- 从 JS Event Loop 机制看 Vue 中 nextTick 的实现原理