js装饰器及call和apply

98 阅读2分钟

装饰器定义

装饰器,听起来是个很高大上的东西,其实它不是js的新语法,只是对js的另类应用,被大众所接受从而出现的一个词,类似防抖、节流。
装饰器被nodejs的很多框架大量应用,比如nestJs、midway等。
装饰器定义:在不修改原函数的基础上,对原函数进行扩展,实现在调用原函数之前先进行处理数据。

来个例子吧

function slow(x){
    return x*2
}

有一个函数slow(x),对于相同的参数,返回相同的值。如果经常调用此函数,我们希望把结果记录下来。那么你首先想到的可能是这样

function slow(x){
    let cache=new Map()
    if(cache.has(x)){
        console.log('读取缓存了');
        return cache.get(x)
    }
    let result=x*2
    cache.set(x,result)
    return result
}

当然这样写也没问题,但是你改变了原函数,这样就不利于扩展了,得想办法在不改变原函数的情况下实现此功能,那么就引出了下边的这种写法

function slow(x){
    return x*2
}
function cachingDecorator(callBack){
    let cache=new Map()
    return function(x){
        if(cache.has(x)){
            console.log('读取缓存了');
            return cache.get(x)
        }
        let result=callBack(x)
        cache.set(x,result)
        return result
    }
}
slow=cachingDecorator(slow)
console.log(slow(5));
console.log(slow(5));

看到这里,恭喜你,你已经学会了装饰器。这个东西平常写代码可能用不到,但是如果开发框架或者第三方库供别人使用,就离不开了。

下边再来个例子

试着把下边的fullName函数添加一个修饰器

fullName={
    lastName(){
        return '三'
    },
    sayHello(firstName){
        alert(firstName+this.lastName())
    }
}

如果你前边都学会了,你可能会这样写

fullName={
    lastName(){
        return '三'
    },
    sayHello(firstName){
        alert(firstName+this.lastName())
    }
}
function nameDecorator(callBack){
    return function(firstName){
        callBack(firstName)
    }
}
fullName.sayHello=nameDecorator(fullName.sayHello)
fullName.sayHello('张')

this.lastName is not a function,是的,它会提示这个玩意,如果你对js的this指向比较熟的话,你会知道这里的this指向的是window,有句顺口溜函数内的this,谁调用this就是谁,如果没有对象调用,默认是window,改变this指向,于是引出了call和apply

call和apply

这两个函数功能没有区别,只是传参的方式不同,具体区别直接百度吧,改下上边的例子,使其正常运行

fullName={
    lastName(){
        return '三'
    },
    sayHello(firstName){
        alert(firstName+this.lastName())
    }
}
function nameDecorator(callBack){
    return function(firstName){
        callBack.call(this,firstName)
    }
}
fullName.sayHello=nameDecorator(fullName.sayHello)
fullName.sayHello('张')