-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ES6 系列之我们来聊聊装饰器 #109
Comments
nice |
mark |
赞 👍 |
如果是方法里面是异步的,如何通过装饰器模式实现日志、方法完成时间的记录呢? |
log应用中 完善的写法 ,我这里一直报TypeError...... 你们呢 |
感觉这个可以用async await或者直接在回调里确定时间 |
完善的写法调用的时候跟上面不太一样。上面是这样的:
而完善的写法应该用这个:
|
只是感觉debounce方法写的有问题,我没有验证 if (timeout) clearTimeout(timeout); // timeout 为true 执行完这句 timeout 为 false
if (immediate) { // 由于immediate = true 会进入
var callNow = !timeout; // 由于timeout 为false 所以callNow 为true
timeout = setTimeout(function(){
timeout = null;
}, wait) // 此时 timeout 为 true 又会重复上面的过程
if (callNow) func.apply(context, args) // 该方法执行
} |
你好, 我有个疑惑, 为什么 |
clearTimeout只会停止定时器 不会把值清空 |
判断类型 然后用promise包裹执行 |
|
autobind 这个装饰器,如果调用 setter 设置新函数,getter 是不是还是会返回最原始的函数? |
Decorator
装饰器主要用于:
装饰类
装饰方法或属性
Babel
安装编译
我们可以在 Babel 官网的 Try it out,查看 Babel 编译后的代码。
不过我们也可以选择本地编译:
新建 .babelrc 文件
再编译指定的文件
装饰类的编译
编译前:
编译后:
我们可以看到对于类的装饰,其原理就是:
装饰方法的编译
编译前:
编译后:
装饰方法的编译源码解析
我们可以看到 Babel 构建了一个 _applyDecoratedDescriptor 函数,用于给方法装饰。
Object.getOwnPropertyDescriptor()
在传入参数的时候,我们使用了一个 Object.getOwnPropertyDescriptor() 方法,我们来看下这个方法:
顺便注意这是一个 ES5 的方法。
举个例子:
第一部分源码解析
在 _applyDecoratedDescriptor 函数内部,我们首先将 Object.getOwnPropertyDescriptor() 返回的属性描述符对象做了一份拷贝:
那么 initializer 属性是什么呢?Object.getOwnPropertyDescriptor() 返回的对象并不具有这个属性呀,确实,这是 Babel 的 Class 为了与 decorator 配合而产生的一个属性,比如说对于下面这种代码:
Babel 就会编译为:
此时传入 _applyDecoratedDescriptor 函数的 descriptor 就具有 initializer 属性。
第二部分源码解析
接下是应用多个 decorators:
对于一个方法应用了多个 decorator,比如:
Babel 会编译为:
在第二部分的源码中,执行了 reverse() 和 reduce() 操作,由此我们也可以发现,如果同一个方法有多个装饰器,会由内向外执行。
第三部分源码解析
如果 desc 有 initializer 属性,意味着当装饰的是类的属性时,会将 value 的值设置为:
而 context 的值为
_class.prototype
,之所以要call(context)
,这也很好理解,因为有可能最后无论是装饰方法还是属性,都会执行:
由此可见,装饰方法本质上还是使用
Object.defineProperty()
来实现的。应用
1.log
为一个方法添加 log 函数,检查输入的参数:
再完善点:
2.autobind
我们很容易想到的一个场景是 React 绑定事件的时候:
我们来写这样一个 autobind 函数:
3.debounce
有的时候,我们需要对执行的方法进行防抖处理:
我们来实现一下:
4.time
用于统计方法执行的时间:
5.mixin
用于将对象的方法混入 Class 中:
mixin 的一个简单实现如下:
6.redux
实际开发中,React 与 Redux 库结合使用时,常常需要写成下面这样。
有了装饰器,就可以改写上面的代码。
相对来说,后一种写法看上去更容易理解。
7.注意
以上我们都是用于修饰类方法,我们获取值的方式为:
但是如果我们修饰的是类的实例属性,因为 Babel 的缘故,通过 value 属性并不能获取值,我们可以写成:
参考
ES6 系列
ES6 系列目录地址:https://github.com/mqyqingfeng/Blog
ES6 系列预计写二十篇左右,旨在加深 ES6 部分知识点的理解,重点讲解块级作用域、标签模板、箭头函数、Symbol、Set、Map 以及 Promise 的模拟实现、模块加载方案、异步处理等内容。
如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。
The text was updated successfully, but these errors were encountered: