zoukankan      html  css  js  c++  java
  • 轻松理解JavaScript闭包

    摘要

    闭包机制是JavaScript的重点和难点,本文希望能帮助大家轻松的学习闭包

    一、什么是闭包?

    闭包就是可以访问另一个函数作用域中变量的函数
    下面列举出常见的闭包实现方式,以例子讲解闭包概念

    function f1(){
        var n=999;
        nAdd=function(){n+=1}
        function f2(){
          alert(n);
        }
        return f2;
      }
      var result=f1();
      result(); // 999
      nAdd();
      result(); // 1000
    
    

    f1是f2的父函数,而f2被赋给了一个全局变量(return的值),这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收,这便形成了闭包。
    因此,可以这么理解。闭包机制就是,如果A函数引用了另一个函数B的变量,但是B返回后A仍没有返回,仍存在,因为A的引用,所以B的所有局部变量并不会随B退出而注销,会一直存在,直到A注销。此时A就是闭包。

    二、闭包的this指针

    闭包通常在全局环境调用的,所以this通常指向window,具体情况还是需要视执行环境而言,总之this指向执行环境。
    若需要闭包的this指向闭包的包含对象,则需要将包含对象的this作为变量传进闭包。

    三、使用闭包的注意点

    1. 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

    2. 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

    四、解决一道闭包常见面试题

    问题:

    
    function onMyLoad(){
                /*
                抛出问题:
                    此题的目的是想每次点击对应目标时弹出对应的数字下标 0~4,但实际是无论点击哪个目标都会弹出数字5
                问题所在:
                    arr 中的每一项的 onclick 均为一个函数实例(Function 对象),这个函数实例也产生了一个闭包域,
                    这个闭包域引用了外部闭包域的变量,其 function scope 的 closure 对象有个名为 i 的引用,
                    外部闭包域的私有变量内容发生变化,内部闭包域得到的值自然会发生改变
                */
                var arr = document.getElementsByTagName("p");
                for(var i = 0; i < arr.length;i++){
                    arr[i].onclick = function(){
                        alert(i);
                    }
                }
            }
    
    

    解决方法
    1、在外面再加一层函数,将i作为函数参数传进来,这样每次保存的是函数内部的变量,与外部i不是同一个内存空间,而每次调用函数都会生成一个局部变量,所以可以保证每次保存的值互不影响。

    for(var i = 0; i<arr.length;i++){
        arr[i].onclick = (function(arg){
            return function () {
                alert(arg);
            }
        })(i);
    }
    
    

    2、用ES6新特let,将for循环的var i改成let i,这样当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。

    更多前端技术文章,欢迎前往我的技术博客:嵘么么的个人博客

  • 相关阅读:
    awk去重以某列重复的行
    awk 统计文件中按照某列统计某列的和(sum)
    使用jdk压缩war包
    histoty显示时间戳
    awk统计文件中某关键词出现次数
    Jbox帮助文档,默认的属性含义
    net之session漫谈及分布式session解决方案
    StackExchange.Redis 基本使用 (一) (转)
    Sql Server 表创建以及Ef浅谈
    数据验证(自定义特性)
  • 原文地址:https://www.cnblogs.com/rongmm/p/6547215.html
Copyright © 2011-2022 走看看