zoukankan      html  css  js  c++  java
  • 从闭包案例中学习闭包的作用,会不会由你。

      在文章初识js中的闭包中讲解了闭包的一些概念,但是对于初学者来说可能并不是特别的容易理解,我今天用两个案例来解释闭包可能会好理解一些,在讲案例之前,我们需要了解一些闭包的概念。在看这篇文章之前,请先看上面的那篇文章,不然效果不会太好。

    闭包的理解:

      所谓的闭包就是可以创建一个独立的环境,每个闭包里面的环境都是独立的,互不干扰。

    闭包的创建:

      一个函数中嵌套另外一个函数,并且将这个函数return出去,然后将这个return出来的函数保存到了一个变量中,那么就创建了一个闭包。

    为啥要学闭包之没有使用闭包的情况1:

    var arr = [];
    for(var i=0;i<2;i++){
        arr[i] = function(){
            console.log(i);
        }
    }
    arr[0](); //2
    arr[1](); //2

      实际情况我们是要打印0,1,2,3这样的数,但是每次都是打印2,什么情况呢?虽然我们在for中给arr的每个值添加了一个匿名函数,但是在for循环中我们并没有执行这个函数,而是在for循环以后执行的这个函数,那么自然打印出来的就是for循环完以后i的值。

    var arr = [];
    // for(var i=0;i<2;i++){
        var i = 2;
        arr[0] = function(){
            console.log(i);
        }
        arr[1] = function(){
            console.log(i);
        }
    // }
    arr[0](); //2
    arr[1](); //2

      相当于这样,虽然这个函数没有执行,但是arr的i已经给执行了,因为arr不是函数啊,肯定是执行的,而你函数没有调用自然就不会执行,当函数调用的时候i已经是2了。既然如此只要我们在for循环的时候直接执行这个函数就ok。

    var arr = [];
    for(var i=0;i<2;i++){
        arr[i] = function(){
            console.log(i);
        }
        arr[i]();
    }
    //0
    //1

      这样,在每一次for循环的时候就直接执行了这个函数,打印正常,但是我们这样同样有一个问题,那就是在每一次for循环的时候这个函数就已经被执行了,我们要的是我们想什么时候调用就时候调用,而不是直接在for执行中直接执行,那么显然这样做是达不到我们的目的的。

      现在我们在想想闭包的概念,闭包可以创建独立的环境,并且每一个闭包的环境是独立的,也就是说,我们可以通过闭包来保存这些不同的变量。

    var arr = [];
    for(var i=0;i<2;i++){
        arr[i] = function(){
            console.log(i);
        }
    }

      还是这段代码,我们回顾一下闭包的创建方法:一个函数中嵌套另外一个函数,并且将这个函数return出去,然后将这个return出来的函数保存到了一个变量中,那么就创建了一个闭包。

    var arr = [];
    for(var i=0;i<2;i++){
        arr[i] = a(i);
    }
    
    function a(i){
        return function(){
            console.log(i);
        }
    }
    
    arr[0](); //0
    arr[1](); //1

       此时就是一个闭包,这样写有些麻烦,我们对此改进一下。

    var arr = [];
    for(var i=0;i<3;i++){
        arr[i] = (function(i){
            return function(){
                console.log(i);
            }
        })(i)
    }
    
    arr[0](); //0
    arr[1](); //1
    arr[2](); //2

      如果你对()包含起来的函数有些疑惑,对匿名函数的深入理解(彻底版)这篇文章深入的讲解了函数的各种调用方式。如果你没有理解建议你从头再看一遍,当然看不看是你的事,反正我是理解了。

      其实还可以这样

    var arr = [];
    for(var i=0;i<3;i++){
        (function(i){
            arr[i] = function(){
                console.log(i);
            }
        })(i)
    }
    
    arr[0](); //0
    arr[1](); //1
    arr[2](); //2

      此时arr里面的i用的是闭包里面的i,而不是for中的i,因为我们说过每个闭包的环境都是独立的。

    没有使用闭包的情况2:

    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
    
    var lis = document.getElementsByTagName("li");
    for(var i=0;i<lis.length;i++){
        lis[i].onclick = function(){
            console.log(i); //3
        }
    }

      这个情况和情况1一样都是因为,这个函数在执行的时候这个for循环已经结束了。

    解决方法:

    var lis = document.getElementsByTagName("li");
    for(var i=0;i<lis.length;i++){
        (function(i){
            lis[i].onclick = function(){
                console.log(i);
            }
        })(i)
    }
  • 相关阅读:
    WPF自定义控件与样式(13)-自定义窗体Window & 自适应内容大小消息框MessageBox
    WPF自定义控件与样式(12)-缩略图ThumbnailImage /gif动画图/图片列表
    WPF自定义控件与样式(11)-等待/忙/正在加载状态-控件实现
    WPF自定义控件与样式(10)-进度控件ProcessBar自定义样
    WPF自定义控件与样式(9)-树控件TreeView与菜单Menu-ContextMenu
    WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox
    WPF自定义控件与样式(7)-列表控件DataGrid与ListView自定义样式
    WPF自定义控件与样式(6)-ScrollViewer与ListBox自定义样式
    常用类-CSV---OLEDB
    常用类-ExcelHelper
  • 原文地址:https://www.cnblogs.com/pssp/p/5224509.html
Copyright © 2011-2022 走看看