闭包

闭包

概念

一个外部函数里面套一个内部函数,内部函数调用外部函数的局部变量,当外部函数执行完之后,变量不会释放;

闭包的好处

  1. 可以间接调用函数内部的局部变量。
  2. 可以让这些变量的值始终保持在内存中。(因此要注意不能滥用闭包)
  3. 可以暂存数据,给变量开辟私密空间,避免外部污染。

闭包的坏处

  1. 内存消耗
  2. 性能问题

通常来说,函数的活动对象会随着执行期上下文一起销毁,但是,由于闭包引用另外一个函数的活动对象,因此这个活动对象无法被销毁,这意味着,闭包比一般的函数需要更多的内存消耗。尤其在IE浏览器中需要关注。由于IE使用非原生javascript对象实现DOM对象,因此闭包会导致内存泄露问题

使用闭包时,会涉及到跨作用域访问,每次访问都会导致性能损失。
因此在脚本中,最好小心使用闭包,它同时会涉及到内存和速度问题。不过我们可以通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度
的影响

闭包存在的坑

  1. 坑一:内存泄漏。比如要为某个元素添加onclick事件的时候
    function showId () {
        var el = document.getElementById('test');
        el.onclick = function () {
            alert(el.id);
        }
    }

这样写会造成内存泄露,换成下面的写法:

    function showId () {
        var el = document.getElementById('test');
        var id = el.id;
        el.onclick = function () {
            alert(id); //这样写会导致id去访问外部函数作用域的id,造成内存泄漏
        }
        el = null;
    }
  1. this的指向问题
    var object = {
        name: '对象',
        getName: function () {
            return function (){
                console.log(this.name);
            }
        }
    }
    
    object.getName()();//打印啥?

打印出来的居然是undefined,第一个括号结束过后是一个函数,你调用了一个全局函数而已嘛

  1. 坑3:引用的变量可能发生变化。(最常见的,以前分享提到过)
function outer(){
    var result = [];
    for(var i=0;i<10;i++) {
        result[i] = function (){
            alert(i);
        }
    }
    return result;
}
outer().forEach(fun => {
    fun();
})

这样会打印出10个10,而不是09,要把他变成立即执行函数才会变成09。因为每次function不是立即执行,得到的是一个序列,等到执行函数时,变量已经迭代到10,所以引用的值变成了10

修改

function outer(){
    var result = [];
    for(var i=0;i<10;i++) {
        result[i] = function (){
            alert(i);
        }(i)
    }
    return result;
}
outer().forEach(fun => {
    fun();
});

应用

<ul id="ul1"> 
    <li>item 1</li>
    <li>item 2</li> 
    <li>item 3</li> 
</ul> 
<script> 
    var oUl = document.getElementById('ul1');
    var aLi = oUl.getElementsByTagName('li');
    for (var i = 0; i < aLi.length; i++) {
        (function (index) {
            aLi[index].onclick = function () {
                alert(index)
            }
        })(i);
    }
    // es6
    for(let i = 0; i < aLi.length; i++) {
        aLi[i].onclick = function () {
            console.log('ES6-' + i)
        }
    }
    // 非闭包的方式
    for(var i = 0; i < aLi.length; i++) {
        aLi[i].index = i;
        aLi[i].onclick = function () {
            alert(this.index)
        }
    }
    // jq实现
    $(document).ready(function () {
        $("#ul1 li").click(function () {
            alert($(this).index());
        })
    })
</script>
{/* // 利用闭包,每次调用都自增1,立即调用函数 */}
var add = (function () {
    // 声明一变量,由于下面 return所以变量只会声明一次 
    var count = 0;
    return function () {
        return console.log(count++);
    };
})();
add(); // 0
add(); // 1
add(); // 2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值