闭包

// 闭包
// 何为闭包?: 有权访问另外一个函数作用域中变量的函数,简单形式就是:外部函数中生成一个内部函数,并通过return来返回,内部函数可以访问外部函数作用域中的函数,因此,外部函数调用之后变量对象本该被销毁,但由于闭包的存在,我们仍然可以在全局访问外部函数的变量。
// 关键:闭包引用外部函数的变量;在外部函数的外部调用闭包
// 注意事项:函数的作用域会一直保存到闭包不存在
// example:
function arrFn(){
    var arr = []
    for(var i=0;i<10;i++){
        arr[i] = function(){
            return i
        }
    }
    return arr
}
arrFn().map(((ele)=>{
    console.log(ele())
}))
// 输出为10个10
// arr数组中为10个匿名函数,当arrFunc执行完毕之后,作用域被销毁,但是变量对象仍然保存在内存中得以被匿名访问,遍历数组执行数组中的每个匿名函数时,匿名函数访问的i均为10

function arrFunc(){
    var arr = []
    for(var i=0;i<10;i++){
        arr[i] = (function(){
            return i;
        })()
    }
    return arr;
}
console.log("arrFunc",arrFunc())
// 返回[0,1,2,3,4,5,6,7,8,9] arr数组中保存的是匿名函数立即执行后的返回值

// 匿名函数外层再嵌套一层函数,来保存循环过程中的每个i值
function arrFunc2(){
    var arr = []
    for(var i=0;i<10;i++){
        arr[i] = function(num){
            return (function(){
                return num;
            })
        }(i)
    }
    return arr
}
arrFunc2().map((ele)=>{
    console.log("arrFunc2",ele())
})
// 输出为 0-9

// 闭包的使用场景

// 1. 封装变量
// 场景:数据请求,上一次数据请求结果返回后,才能进行下次请求,设置flat标志是否请求完成 false-未结束,true--请求结束
// 未使用闭包
var flat = false
var fn = function () {
    if(flat){
        // ajax进行数据请求
        $.ajax({
            url: '',
            data: {},
            type: 'json',
            success: function () {
            },
            complete: function () {
                flat = true
            }
        })
    }else{
        return;
    }
}
// 使用闭包来写
var fn = function () {
    var flat = false
    return (function () {
        if(flat){
            // ajax进行数据请求
            $.ajax({
                url: '',
                data: {},
                type: 'json',
                success: function () {
                },
                complete: function () {
                    flat = true
                }
            })
        }else{
            return;
        }        
    })
}
// var f = fn()
// f()
// VS: 不使用闭包,flat为全局变量暴露在全局,污染全局环境,使用闭包 flat作为局部变量,进行封装,不会被全局中其他方法访问/改变

// 2. 利用闭包,返回/生成其他的函数
// 场景: 邀新banner为例,不同的module_id对应执行不同的方法
// 不使用闭包
// if(module_id === 'invite0'){
//     f1()
// }else if(module_id === 'inviteN'){
//     f2()
// }
// 使用闭包
var action = function(module_id){
    // if(module_id === 'invite0'){
    //     return (function () {
    //         // "invite0"时执行的方法
    //     })()
    // }else if(module_id === 'inviteN'){
    //     return (function () {
    //         // "inviteN"时执行的方法
    //     })()
    // }
    // 优化:
    var map = {
        "invite0": function () {
            console.log("0")
        },
        "inviteN": function () {
            console.log("N")
        }
    }
    return map[module_id]()
}
// action("invite0")
// VS: 利用闭包将不同module_id执行不同方法 封装成一个方法,使用时,直接调用action即可,

// 3. 解决浏览器兼容性问题
// 添加事件监听为例
// 不使用闭包

// 使用闭包
// 闭包一
var addEventListener = function (dom, type, fn) {
    if(dom.addEventListener){
        return (function () {
            dom.addEventListener(type, fn, false)
        })()
    }else{
        return (function () {
            dom.attachEvent("on"+type, fn)
        })()
    }
}
// 闭包二: 上述闭包 每次调用闭包方法都会进行一次dom.addEventListener的判断 -- 只在第一次运行的时候判断
var addEventListener = function (dom, type, fn) {
    if(dom.addEventListener){
        return (function () {
            addEventListener = dom.addEventListener(type, fn, false)
        })()
    }else{
        return (function () {
            addEventListener = dom.attachEvent("on"+type, fn)
        })()
    }
}

// 4. 函数科里化
// 预设情景: add方法,实现 add(1) add(2) add(3) add() : 调用add方法,当没有参数时,对前面添加的
var add = function (arr) {
    var result = 0
    for(let i=0;i<arr.length;i++){
        result += arr[i]
    }
    return result
}
var addEv = function (...args) {
    var array = args
    return (function(...arg){
        if(arg.length === 0){
            return add(array)
        }else{
            array = array.concat(arg)
        }
    })
}
var a = addEv(1,2)
a(3,4)
a(5)
a() //求和:15


// 闭包中的this指向  --注意下面代码需作为html的脚本文件运行,不要利用run code直接运行脚本文件
var name = "window"
var obj = {
    name: "object",
    getName: function(){
        return function(){
            return this.name
        }
    }
}
console.log(obj.getName()())
// 匿名函数的执行具有全局性,匿名函数中的this指向全局,输出为window
// 要使this指向外部函数环境,下面的写法
var obj2 = {
    name: "object2",
    getName: function(){
        let _this = this
        return function(){
            return _this.name
        }
    }
}
console.log(obj2.getName()()) // object2

// 闭包引起的内存泄漏
// js中的垃圾回收机制
// 1. 标记清除: 垃圾运行机制运行时,会给存储在内存中所有的变量都加上标记,然后会清除掉环境中变量的标记和被变量引用的变量的标记,此后如果变量再被标记,则表示该变量准备被删除
// 2. 引用计数: 跟踪记录每个值被引用的次数,声明一个变量被将一个引用类型的值赋给它,这个值的引用次数为1,当这个值被赋值给另外一个变量,引用次数加1,如果一个变量脱离这个值的引用,这个值的引用次数减1,当一个值的引用次数为0,就会等待垃圾回收器的回收。
// 引用计数策略来进行垃圾回收时:存在循环引用时,会造成内存泄漏(不再使用的内存不能被清楚,占用内存资源)
window.onload = function(){
    var element = document.getElementById("id")
    element.onclick = function(){
        alert(element.id)
    }
}
// 存在循环引用:匿名函数赋给element的onclick属性,匿名函数中又调用了element的id
window.onload = function(){
    var element = document.getElementById("id")
    var id = element.id // 解除循环引用
    element.onclick = function(){
        alert(id)
    }    
    element = null // 引用对象清除
}

// 定时器清除
(function(){
    var a = 0
    let timer = setTimeout(function(){
        console.log(a++)
    },1000)
})()
// 定时器内引用外部函数变量对象,循环引用
// clearTimeout(this.timer)
// this.timer = null

// 总结:
// 闭包优缺点:优: 私有化变量,避免全局环境污染;缺: 内存泄漏
// 面试题:
function fun(n,o){
    console.log(o)
    return {
        fun: function(m){
            return fun(m,n)
        }
    }
}
var a = fun(0) // undefined
a.fun(1) // 0
a.fun(2) // 0
a.fun(3) // 0
var b = fun(0).fun(1).fun(2).fun(3) // undefined 0 1 2
var c = fun(0).fun(1) // undefined 0
c.fun(2) // 1
c.fun(3) // 1

以下是对提供的参考资料的总结,按照要求结构化多个要点分条输出: 4G/5G无线网络优化与网规案例分析: NSA站点下终端掉4G问题:部分用户反馈NSA终端频繁掉4G,主要因终端主动发起SCGfail导致。分析显示,在信号较好的环境下,终端可能因节能、过热保护等原因主动释放连接。解决方案建议终端侧进行分析处理,尝试关闭节电开关等。 RSSI算法识别天馈遮挡:通过计算RSSI平均值及差值识别天馈遮挡,差值大于3dB则认定有遮挡。不同设备分组规则不同,如64T和32T。此方法可有效帮助现场人员识别因环境变化引起的网络问题。 5G 160M组网小区CA不生效:某5G站点开启100M+60M CA功能后,测试发现UE无法正常使用CA功能。问题原因在于CA频点集标识配置错误,修正后测试正常。 5G网络优化与策略: CCE映射方式优化:针对诺基亚站点覆盖农村区域,通过优化CCE资源映射方式(交织、非交织),提升RRC连接建立成功率和无线接通率。非交织方式相比交织方式有显著提升。 5G AAU两扇区组网:与三扇区组网相比,AAU两扇区组网在RSRP、SINR、下载速率和上传速率上表现不同,需根据具体场景选择适合的组网方式。 5G语音解决方案:包括沿用4G语音解决方案、EPS Fallback方案和VoNR方案。不同方案适用于不同的5G组网策略,如NSA和SA,并影响语音连续性和网络覆盖。 4G网络优化与资源利用: 4G室分设备利旧:面对4G网络投资压减与资源需求矛盾,提出利旧多维度调优策略,包括资源整合、统筹调配既有资源,以满足新增需求和提质增效。 宏站RRU设备1托N射灯:针对5G深度覆盖需求,研究使用宏站AAU结合1托N射灯方案,快速便捷地开通5G站点,提升深度覆盖能力。 基站与流程管理: 爱立信LTE基站邻区添加流程:未提供具体内容,但通常涉及邻区规划、参数配置、测试验证等步骤,以确保基站间顺畅切换和覆盖连续性。 网络规划与策略: 新高铁跨海大桥覆盖方案试点:虽未提供详细内容,但可推测涉及高铁跨海大桥区域的4G/5G网络覆盖规划,需考虑信号穿透、移动性管理、网络容量等因素。 总结: 提供的参考资料涵盖了4G/5G无线网络优化、网规案例分析、网络优化策略、资源利用、基站管理等多个方面。 通过具体案例分析,展示了无线网络优化中的常见问题及解决方案,如NSA终端掉4G、RSSI识别天馈遮挡、CA不生效等。 强调了5G网络优化与策略的重要性,包括CCE映射方式优化、5G语音解决方案、AAU扇区组网选择等。 提出了4G网络优化与资源利用的策略,如室分设备利旧、宏站RRU设备1托N射灯等。 基站与流程管理方面,提到了爱立信LTE基站邻区添加流程,但未给出具体细节。 新高铁跨海大桥覆盖方案试点展示了特殊场景下的网络规划需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值