惰性函数

定义

惰性函数解决了这类问题:
第一次调用这个方法时,返回一个值;后面每次调用都返回第一次计算出来的值。

举个例子:

例子来自文章
我们现在需要写一个 foo 函数,这个函数返回首次调用时的 Date 对象,注意是首次。
可以轻易的想到几种方法

全局变量法

let t
const foo = ()=> {
    if(t) return t
    t = new Date;
    return t
}

这种方法有两个缺点:污染全局变量、每次都需要做一个判断(if(t)

看到「污染全局变量」我们自然而然的就会想到用闭包来处理

闭包

    const foo = ()=>{
        let t;
        return function(){
            if(t)return t
            t = new Date()
            return t
        }
    }

这样做之后,污染全局变量的问题解决了,但是每次都需要判断还是没被解决
还有其他的实现方案吗?

函数对象法

js 里函数也是对象,所以可以把变量挂在函数上

const foo = () =>{
    if(foo.t) return foo.t
    foo.t = new Date()
    return foo.t
}

又是一种解决方案,等等,这不是和闭包法一样嘛,污染全局变量的问题解决了,但是每次都需要判断还是没被解决。
那有没有什么做法能不需要判断呢;答案就是惰性函数。在运行一次后,就把自身改变了

惰性函数

const foo = ()=>{
    let t = new Date()
    foo = () => t
    return foo()
}

仅第一次运行的时候执行了new Date(),以后再也不会执行了。

应用场景

一个典型的「每次都需要进行条件判断,其实只需要判断一次」的场景如下:
我们有一个获取打印机列表的方法:在 Mac 系统是getMacPrinterList 在 Windows 系统是 getWinPrinterList(假设不用考虑其他系统)
以前我们通常这么写

function getPrinterList (){
    let isMac = /macintosh|mac os x/i.test(navigator.userAgent)
    if(isMac){
        return getMacPrinterList()
    }else{
        return getWinPrinterList()
    } 
}

使用惰性函数,我们可以这么写

function getPrinterList (){
    let isMac = /macintosh|mac os x/i.test(navigator.userAgent)
    if(isMac){
        getPrinterList =  getMacPrinterList
    }else{
        getPrinterList =  getWinPrinterList
    } 
    return getPrinterList()
}
Comments
Write a Comment