参考资料:都2020年了,你还不会JavaScript 装饰器? 装饰器目前还是提案,新提案似乎还未出来,出来之后可能语法会发生改变,因此装饰器目前用的也不多。浏览器上还无法直接使用。不属于ES6
target:被修饰的类
name:类成员的名字
descriptor:属性描述符,对象会将这个参数传给 Object.defineProperty
// 语法
const withSpeak = (targetClass) = {
targetClass.speak = 'hello'
}
@withSpeak
class Student{
}
cosnt stu = new Student()
stu.speak // 'hello'
const withLanguage = (language) => (targetClass) => {
targetClass.prototype.language = language;
}
@withLanguage('Chinese')
class Student {
}
const student = new Student();
student.language; // 'Chinese'
// 类属性装饰器
function readonly(target, name, descriptor) {
descriptor.writable = false;
return descriptor;
}
class Person {
@readonly name = 'person'
}
const person = new Person();
person.name = 'tom';
例子:time装饰器,用来统计一个函数的执行时间,以便于后期做一些性能优化:
function time(target, name, descriptor) {
const func = descriptor.value;
if (typeof func === 'function') {
descriptor.value = function(...args) {
console.time();
const results = func.apply(this, args);
console.timeEnd();
return results;
}
}
}
class Person {
@time
say() {
console.log('hello')
}
}
const person = new Person();
person.say();
节流throttle:
const throttle = (time) => {
let prev = new Date();
return (target, name, descriptor) => {
const func = descriptor.value;
if (typeof func === 'function') {
descriptor.value = function(...args) {
const now = new Date();
if (now - prev > wait) {
fn.apply(this, args);
prev = new Date();
}
}
}
}
}
// use
class App extends React.Component {
componentDidMount() {
window.addEveneListener('scroll', this.scroll);
}
componentWillUnmount() {
window.removeEveneListener('scroll', this.scroll);
}
@throttle(50)
scroll() {}
}
防抖debounce:
const debounce = (time) => {
let timer;
return (target, name, descriptor) => {
const func = descriptor.value;
if (typeof func === 'function') {
descriptor.value = function(...args) {
if(timer) clearTimeout(timer)
timer = setTimeout(()=> {
fn.apply(this, args)
}, wait)
}
}
}
}
core-decorators是一个封装了常用装饰器的 JS 库。