资讯专栏INFORMATION COLUMN

闭包

Jokcy / 2130人阅读

摘要:闭包,获取一个局部作用域里变量的访问权限,涉及到作用域栈执行上下文垃圾回收机制内存驻留以及性能问题,闭包切断作用域栈产生的垃圾回收事件,实现变量的内存驻留。因而,为避免产生严重的性能问题,在完成事件任务后要把闭包置为,释放内存。

闭包,获取一个局部作用域里变量的访问权限,涉及到作用域栈、执行上下文、垃圾回收机制、内存驻留以及性能问题,闭包切断作用域栈产生的垃圾回收事件,实现变量的内存驻留。主要应用场景在需要累积效应、重复循环事件、前后事件相关等。因而,为避免产生严重的性能问题,在完成事件任务后要把闭包置为null,释放内存。

这里介绍JS中作用域栈的特性,即先进后出,全局作用域位于栈底,局部作用域按照编译、执行顺序依次入栈,执行完毕依次出栈,对变量进行垃圾回收,释放内存。了解此特性,利用全局作用域始终位于栈底,并且总是最后完成垃圾回收,只要在局部作用域中装载具有全局效应的作用域,阻断垃圾回收,就完成了闭包的设计。

示例1

function foo(x) {
    var tmp = 3;
    return function (y) {
        console.log(x + y + tmp);
        x.memb = x.memb ? x.memb + 1 : 1;
        console.log(x.memb);
    }
}
var age = new Number(2);
var bar = foo(age); // bar 现在是一个引用了age的闭包
bar(10);

示例2

function foo(x) {
    var temp = 3;
    return function (y) {
        console.log(x + y + (++temp));
    }
}
var bar = foo(2);
bar(10);

示例3

function badClosureExample() {
    var as = document.querySelectorAll("a");
    for (var i = 0; i < 4; i++) {
        as[i].onclick = new popNum(i);
        function popNum(oNum) {
            return function () {
                alert("单击第" + oNum + "个");
            }
        }
    }
}
badClosureExample();

示例4

 function badClosureExample() {
    var as = document.querySelectorAll("a");
    for (var i = 0; i < 4; i++) {
        (function (i) {
            as[i].onclick = function () {
                alert("单击第" + i + "个");
            }
        })(i);
    }
}
badClosureExample();

1、将变量 i 保存给在每个段落对象(p)上

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        pAry[i].i = i;
        pAry[i].onclick = function () {
            alert(this.i);
        }
    }
}
init();

2、将变量 i 保存在匿名函数自身

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        (pAry[i].onclick = function () {
            alert(arguments.callee.i);
        }).i = i;
    }
}
init();

3、加一层闭包,i 以函数参数形式传递给内层函数

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        (function (i) {
            pAry[i].onclick = function () {
                alert(i);
            }
        })(i);//调用时参数
    }
}
init();

4、加一层闭包,i 以局部变量形式传递给内层函数

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        (function () {
            var index = i;//调用时局部变量
            pAry[i].onclick = function () {
                alert(index);
            }
        })();
    }
}
init();

5、加一层闭包,返回一个函数作为响应事件(注意与3的细微区别)

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        pAry[i].onclick = function (i) {
            return function () { //返回一个函数
                alert(i);
            }
        }(i)
    }
}
init();

6、用Function实现,实际上每产生一个函数实例就会产生一个闭包

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        pAry[i].onclick = new Function("alert(" + i + ")");
        //new一次就产生一个函数实例
    }
}
init();

7、用Function实现,注意与6的区别

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        pAry[i].onclick =Function("alert(" + i + ")");
    }
}
init();

示例5

var name = "The Window";
var object = {
    name: "My Object",
    getNameFunc: function () {
        return function () {
            return this.name;
        };
    }
};
alert(object.getNameFunc()()); //The Window

示例6

function outerFun() {
    var a = 0;

    function innerFun() {
        a++;
        alert(a);
    }

    return innerFun; //注意这里
}
var obj = outerFun();
obj(); //结果为1
obj(); //结果为2

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82405.html

相关文章

  • JS 中的闭包是什么?

    摘要:大名鼎鼎的闭包面试必问。闭包的作用是什么。看到闭包在哪了吗闭包到底是什么五年前,我也被这个问题困扰,于是去搜了并总结下来。关于闭包的谣言闭包会造成内存泄露错。闭包里面的变量明明就是我们需要的变量,凭什么说是内存泄露这个谣言是如何来的因为。 本文为饥人谷讲师方方原创文章,首发于 前端学习指南。 大名鼎鼎的闭包!面试必问。请用自己的话简述 什么是「闭包」。 「闭包」的作用是什么。 首先...

    Enlightenment 评论0 收藏0
  • 闭包,又见闭包。。。。?

    摘要:完美的闭包,对,闭包就这么简单。这仅仅是闭包的一部分,闭包利用函数作用域达到了访问外层变量的目的。此时一个完整的闭包实现了,的垃圾回收机制由于闭包的存在无法销毁变量。 1.闭包是指有权访问另一个函数作用域中的变量的函数。 上面这段话来自 javascript 高级程序设计 第三版 P178 。作者说闭包是一个函数,它有访问另一个函数作用域中的变量的能力。 2.函数访问它被创建时所处的...

    keelii 评论0 收藏0
  • 多层级理解闭包

    摘要:第二梯队理解有了第一梯队的认识,我们慢慢修正大脑中对闭包的认识。理解这句话就可以很好的与闭包这两个字关联起来理解闭包这个概念了。总结第二梯队理解闭包是一个有特定功能的函数。第四梯队理解闭包通过访问外部变量,一个闭包可以维持这些变量。 闭包 闭包的概念困惑了我很久,记得当时我面试的时候最后一面有一个问题就是问题关于闭包的问题,然而到现在已经完全不记得当时的题目是啥了,但仍然能够回忆起当时...

    nemo 评论0 收藏0
  • 面试官问我:什么是JavaScript闭包,我该如何回答

    摘要:到底什么是闭包这个问题在面试是时候经常都会被问,很多小白一听就懵逼了,不知道如何回答好。上面这么说闭包是一种特殊的对象。闭包的注意事项通常,函数的作用域及其所有变量都会在函数执行结束后被销毁。从而使用闭包模块化代码,减少全局变量的污染。 闭包,有人说它是一种设计理念,有人说所有的函数都是闭包。到底什么是闭包?这个问题在面试是时候经常都会被问,很多小白一听就懵逼了,不知道如何回答好。这个...

    BenCHou 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<