• 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;
                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;  
                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;    
                    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


  • 相关阅读:
    百度--买帽子
    网易--双核处理器
    京东--通过考试
    简单错误记录
    链表中的倒数第k个结点
    数值的整数次方
    二进制中1的个数
    TCP 三次握手
    旋转数组的最小数字
    用两个栈实现队列
  • 原文地址:https://www.cnblogs.com/xutongbao/p/9924991.html
Copyright © 2020-2023  润新知