js闭包的应用和优缺点

闭包应用

封装一个具有特定功能的JS模块,将所有数据和功能封装在函数内部,只向外暴露指定的几个方法或者对象,使用者只需通过约定的方法来实现对应的功能
下面来看代码

function NumOperation(params) {
    let num = 10
    function readNum() {
        return num
    }
    function addNum(a) {
        num += a
    }
    function subNum(b) {
        num -= b
    }
    return {readNum,addNum,subNum}
}
let temp = NumOperation()
console.log(temp.readNum()) //10
temp.addNum(2)
console.log(temp.readNum()) //12
temp.subNum(3)
console.log(temp.readNum()) //9
temp = null

这里外面无法直接访问到num,只能通过暴露的几个接口去访问。代码应该很好理解
再看另一种做法

(function NumOperation(window) {
    let num = 10
    function readNum() {
        return num
    }
    function addNum(a) {
        num += a
    }
    function subNum(b) {
        num -= b
    }
    window.NumModel = {readNum,addNum,subNum}
})(window)
console.log(NumModel.readNum()) //10
NumModel.addNum(2)
console.log(NumModel.readNum()) //12
NumModel.subNum(3)
console.log(NumModel.readNum()) //9

这种方法不用像第一种那样去调用函数,这是一个立即执行函数,在引入js代码的时候就会立即执行。

函数的柯里化

什么是柯里化:将一次性传入多个参数的函数转换成一次传入一个参数的函数。就比如下面的验证邮箱,一般函数直接传入正则表达式和要匹配的字符,可是这样做每次都得写一遍正则表达式,这时候就可以用到柯里化,设置分步传参,看下面代码。

//需求:实现验证手机号,和邮箱
function Viv(temple) {
    return function (readViv) {
        return temple.test(readViv)
    }
}
//验证手机号
let template1 = /^1[0-9]{10}$/
let phoneViv = Viv(template1)
let phone1 = '14747231234'
let phone2 = '1475678120'
let phone3 = '01212345678'
console.log(phoneViv(phone1))
console.log(phoneViv(phone2))
console.log(phoneViv(phone3))
let template2 = /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/
let email1 = '2101055795@qq.com'
let email2 = '12.edu.12@qq.com'
let email3 = '23qq.com'
let emailViv = Viv(template2)
console.log(emailViv(email1))
console.log(emailViv(email2))
console.log(emailViv(email3))

求和

// 这个是优化的版本
function add() {
    let sum = 0
    let fn = function () {
        Array.prototype.forEach.call(arguments, item => (sum += item))
        console.log(sum)
        return fn
    }
    fn(...arguments)
    return fn
}
let a = add(1, 2)(3, 4)(8)(4, 5, 6, 7) 


function add() {
    let arg = Array.prototype.slice.call(arguments)
    function _add() {
        if(arguments.length>0){
            arg.push(...arguments)
            return _add
        }else {
            return arg.reduce((pre,cur)=>{
                return pre+cur
            },0)
        }
        
        return _add
    }
    return _add  
}
console.log(add(6)(7)(1,2)())

可见本质上还是用到闭包的特性。

闭包优缺点

函数执行完之后,函数内部的局部变量还没有被释放,占用内存时间会延长,这就容易导致内存泄漏问题,所以要在使用完之后及时的释放内存。如果内存泄漏积累多了就导致了内存溢出。

引申一个知识点this

var name = 'lalal'

let obj = {
    name :'heihei',
    getName : function () {
        return function () {
            console.log(this.name)
        }
    }
}
obj.getName()() // lalal

var name = 'lalal'

let obj1 = {
    name :'heihei',
    getName : function () {
        let that = this
        return function () {
            console.log(that.name)
        }
    }
}
obj1.getName()() // heihei

第一个和第二个输出明显是不同的,这是因为执行上下文是不同的,第一个调用getName返回函数,再执行返回函数,返回函数的执行是在window环境下执行的,它处于的上下文是window,所以this.name是window中的name, 第二个再调用getName的时候函数this是指向obj对象,此时用闭包的原理用that存储了当前的上下文obj1,再执行返回函数的时候,返回函数的执行虽然再window上下文,可是里面的that指向的是obj1的上下文。
这里相关的可以看我的博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程小飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值