javascript闭包浅析

    //闭包
	var myObjectNew = (function () {
		var value = 0;
		return {
			increment: function (inc) {
				value += typeof inc === 'number' ? inc : 1;
            },
			getValue: function () {
				return value;
            }
		}
    }());

	var quo = function (status) {
		return {
			get_status: function () {
				return status;
            }
		}
    };

	var myQuoNew = quo('amazed');
	console.log('status=' + myQuoNew.get_status());



当我们调用quo时,它返回包含get_status方法的一个新对象。该对象的一个引用保存在myQuo中。即使quo已经返回了,但get_status方法仍然享有访问quo对象的status属性的特权。get_status方法并不是访问该参数的一个副本,它访问的就是该参数本身。这是可能的,因为该函数可以访问它被创建时所处的上下文环境。这被称为闭包。

理解内部函数能访问外部函数的实际变量而无须复制是很重要的


    //糟糕的例子
	//构造一个函数,用错误的方式给一个数组中的节点设置事件处理程序。
	//当点击一个节点时,按照预期,应该弹出一个对话框显示节点的序号。
	//但它总是会显示节点的数目
	var add_the_handlers = function (nodes) {
		var i;
		for (i = 0; i < nodes.length; i++) {
			nodes[i].onclick = function (e) {
				alert(i);
            }
		}
    };


add_the_handlers函数的本意是想传递给每个处理器一个唯一值(i)。但它未能达到目的,因为事件处理器函数绑定了变量i本身,而不是函数在构造时的变量i的值。


    //改良后的例子
    var add_the_handlers_new = function (nodes) {
		var helper = function (i) {
			return function (e) {
				alert(i);
            }
        }
        var i;
        for (i = 0; i < nodes.length; i++) {
            nodes[i].onclick = helper(i + 1);
        }
    };


避免在循环体中创建函数,它可能只会带来无谓的计算,还会引起混淆,正如上面那个糟糕的例子。我们可以先在循环之外创建一个辅助函数,让这个辅助函数再返回一个绑定了当前i值的函数,这样就不会导致混淆了。



复制下面的文件到html文件里即可运行查看效果!


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <style>
        .button{
            font-family:"Arial";border:0;
            vertical-align:middle;margin:8px;line-height:18px;font-size:18px;
            width:140px;height:36px;line-height:18px;font-size:18px;
        }
    </style>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>
</head>
<body>
    <div style="margin-top: 20px">
        <input type="button" class="button" value="按钮1">
        <input type="button" class="button" value="按钮2">
        <input type="button" class="button" value="按钮3">
        <input type="button" class="button" value="按钮4">
        <input type="button" class="button" value="按钮5">
    </div>

    <script type="text/javascript">
        var add_the_handlers_new = function (nodes) {
            var helper = function (i) {
                return function (e) {
                    alert(i);
                }
            }
            var i;
            for (i = 0; i < nodes.length; i++) {
                nodes[i].onclick = helper(i + 1);
            }
        };

        add_the_handlers_new($('.button'));
    </script>
</body>
</html>

闭包的好处有:
1.缓存
2.面向对象中的对象
3.实现封装,防止变量跑到外层作用域中,发生命名冲突
4.匿名自执行函数,匿名自执行函数可以减小内存消耗

闭包的坏处:
1.内存消耗
通常来说,函数的活动对象会随着执行期上下文一起销毁,但是,由于闭包引用另外一个函数的活动对象,因此这个活动对象无法
被销毁,这意味着,闭包比一般的函数需要更多的内存消耗。尤其在IE浏览器中需要关注。由于IE使用非原生javascript对象实现
DOM对象,因此闭包会导致内存泄露问题。
2.性能问题
使用闭包时,会涉及到跨作用域访问,每次访问都会导致性能损失。
因此在脚本中,最好小心使用闭包,它同时会涉及到内存和速度问题。不过我们可以通过把跨作用域变量存储在局部变量中,然后直
接访问局部变量,来减轻对执行速度的影响。

内存泄露
1.定义:一块被分配的内存既不能使用,也不能回收。从而影响性能,甚至导致程序崩溃。
2.起因:JavaScript的垃圾自动回收机制会按一定的策略找出那些不再继续使用的变量,释放其占有的内存。然而由于一些原因
导致在这种机制下内存管理器不能正确解读javascript变量的生命周期,从而没有释放其内存,而也没有再被使用。循环引用是
导致以上情况的主要原因之一。

解决方法:常用的解决方法就是在JavaScript代码段运行完之时将形成循环引用的JavaScript对象手动设置为空,切断引用。



附加:一个朋友给了实现这个功能又不用闭包的方法

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <style>  
        .button{  
            font-family:"Arial";border:0;  
            vertical-align:middle;margin:8px;line-height:18px;font-size:18px;  
            width:140px;height:36px;line-height:18px;font-size:18px;  
        }  
    </style>  
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>  
</head>  
<body>  
    <div style="margin-top: 20px">  
        <input type="button" class="button" value="按钮1">  
        <input type="button" class="button" value="按钮2">  
        <input type="button" class="button" value="按钮3">  
        <input type="button" class="button" value="按钮4">  
        <input type="button" class="button" value="按钮5">  
    </div>  
  
    <script type="text/javascript">  
        var add_the_handlers_new = function (nodes) {   
            for (var i = 0; i < nodes.length; i++) {  
                nodes[i].onclick = function() {
                    var index = $(this).index();
                    alert(index + 1);
                };  
            }  
        };  
  
        add_the_handlers_new($('.button'));  
    </script>  
</body>  
</html>

附加二:如果用ES6也可以

    <!DOCTYPE html>    
    <html lang="en">    
    <head>    
        <meta charset="UTF-8">    
        <style>    
            .button{    
                font-family:"Arial";border:0;    
                vertical-align:middle;margin:8px;line-height:18px;font-size:18px;    
                width:140px;height:36px;line-height:18px;font-size:18px;    
            }    
        </style>    
        <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>    
    </head>    
    <body>    
        <div style="margin-top: 20px">    
            <input type="button" class="button" value="按钮1">    
            <input type="button" class="button" value="按钮2">    
            <input type="button" class="button" value="按钮3">    
            <input type="button" class="button" value="按钮4">    
            <input type="button" class="button" value="按钮5">    
        </div>    
        
        <script type="text/javascript">    
            var add_the_handlers_new = function (nodes) {     
                for (let i = 0; i < nodes.length; i++) {    
                    nodes[i].onclick = function() {  
                        alert(i + 1);  
                    };    
                }    
            };    
        
            add_the_handlers_new($('.button'));    
        </script>    
    </body>    
    </html>  





备注:欢迎加入web前端求职招聘qq群:668352707


转载于:https://www.cnblogs.com/xutongbao/p/9924991.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值