摘要:闭包,获取一个局部作用域里变量的访问权限,涉及到作用域栈执行上下文垃圾回收机制内存驻留以及性能问题,闭包切断作用域栈产生的垃圾回收事件,实现变量的内存驻留。因而,为避免产生严重的性能问题,在完成事件任务后要把闭包置为,释放内存。
闭包,获取一个局部作用域里变量的访问权限,涉及到作用域栈、执行上下文、垃圾回收机制、内存驻留以及性能问题,闭包切断作用域栈产生的垃圾回收事件,实现变量的内存驻留。主要应用场景在需要累积效应、重复循环事件、前后事件相关等。因而,为避免产生严重的性能问题,在完成事件任务后要把闭包置为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
摘要:大名鼎鼎的闭包面试必问。闭包的作用是什么。看到闭包在哪了吗闭包到底是什么五年前,我也被这个问题困扰,于是去搜了并总结下来。关于闭包的谣言闭包会造成内存泄露错。闭包里面的变量明明就是我们需要的变量,凭什么说是内存泄露这个谣言是如何来的因为。 本文为饥人谷讲师方方原创文章,首发于 前端学习指南。 大名鼎鼎的闭包!面试必问。请用自己的话简述 什么是「闭包」。 「闭包」的作用是什么。 首先...
摘要:完美的闭包,对,闭包就这么简单。这仅仅是闭包的一部分,闭包利用函数作用域达到了访问外层变量的目的。此时一个完整的闭包实现了,的垃圾回收机制由于闭包的存在无法销毁变量。 1.闭包是指有权访问另一个函数作用域中的变量的函数。 上面这段话来自 javascript 高级程序设计 第三版 P178 。作者说闭包是一个函数,它有访问另一个函数作用域中的变量的能力。 2.函数访问它被创建时所处的...
摘要:到底什么是闭包这个问题在面试是时候经常都会被问,很多小白一听就懵逼了,不知道如何回答好。上面这么说闭包是一种特殊的对象。闭包的注意事项通常,函数的作用域及其所有变量都会在函数执行结束后被销毁。从而使用闭包模块化代码,减少全局变量的污染。 闭包,有人说它是一种设计理念,有人说所有的函数都是闭包。到底什么是闭包?这个问题在面试是时候经常都会被问,很多小白一听就懵逼了,不知道如何回答好。这个...
阅读 1379·2021-11-11 16:54
阅读 9201·2021-11-02 14:44
阅读 2334·2021-10-22 09:53
阅读 3243·2019-08-30 11:18
阅读 1934·2019-08-29 13:29
阅读 1987·2019-08-27 10:58
阅读 1612·2019-08-26 11:38
阅读 3493·2019-08-26 10:31