文档章节

一段代码理解闭包

PandaTsui
 PandaTsui
发布于 2016/10/10 12:13
字数 901
阅读 56
收藏 1

##实现基本的闭包

####返回一个函数

// 注释: 定义fn接收函数只执行后返回的对象(函数或者包含函数的对象)
// a为要控制的数据变量,方法fn1,fn2控制这个局部变量a
var fn = (function (){
        var a;
        a = 1;
        return function () {
            a += 2;
            alert(a);
        }
        })()
    // 测试代码
    fn(); // 执行a+=2;,输出结果为3
    fn();// 执行a+=2;,输出结果为5
    fn = null; // 垃圾回收,释放内存

####返回一个包含方法的对象

// 注释: 定义fn接收函数只执行后返回的对象(函数或者包含函数的对象)
// a为要控制的数据变量,方法fn1,fn2控制这个局部变量a
var fn = (function (){
        var a,fn1,fn2; // 局部私有变量和方法
        a = 1;
        fn1 = function (){
            a++;
            return a;
        }
        fn2 = function (){
            a--;
            return a;
        }
        return {
            fn1:fn1,
            fn2:fn2
        }
    })()
    
    // 测试代码
    console.log(fn.fn1()); // 执行a++,输出结果为2
    console.log(fn.fn2());// 执行a--,输出结果为1
    console.log(fn.fn1());// 执行a++,输出结果为2
    fn = null; // 垃圾回收

##闭包解决循环内嵌异步函数(事件驱动的函数或定时器函数) ####1.错误的方法

<!DOCTYPE html>
<html xml:lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
    <title>闭包解决循环问题</title>
     <style>
            li {
                height: 30px;
                width: 100px;
                text-align: center;
                line-height: 30px;
                background-color: pink;
                margin-top: 10px;
            }
    </style>
</head>
<body>
<ul>
    <li>列表1</li>
    <li>列表2</li>
    <li>列表3</li>
    <li>列表4</li>
</ul>

<script>
    
var Lis = document.getElementsByTagName('li');
for (var i = 0; i < Lis.length; i++) {
    // 依次给每个li标签注册事件
    Lis[i].onclick = function () {        
        alert(i); // 点击列表1,输出4;点击列表2,输出的也是4;点击3,4结果亦同;
    };
}
</script>
</body>
</html>

####2.运用闭包解决上面问题,只需要改写script标签里的JavaScript代码

   var Lis = document.getElementsByTagName('li');
   for (var i = 0; i < Lis.length; i++) {
       Lis[i].onclick = (function (i) {     
           return function (){
               alert(i); // 点击列表0,输出0;点击列表1,输出1;成功输出正确的值
               // 用闭包包裹变量 i 后,并将全局i通过传参的方式传入,i 变成了函数内的一个局部私有变量,
               // return出的这个事件执行函数里访问不再是全局的 i,而是这个局部变量 i ,此时就能正确输出;
           }
       })(i);
       Lis[i] = null;
   }

####3.当然,闭包并不是解决这个问题的最佳方法,因为闭包存在内存泄露问题尽量不要使用,下面介绍一种通过给DOM节点设置自定义属性方式解决这个问题

   var Lis = document.getElementsByTagName('li');
   for (var i = 0; i < Lis.length; i++) {
       Lis[i].index = i;
       Lis[i].onclick = function () {       
           alert(this.index); // 这里的this指向,调用他的当前DOM节点,也就是当前的 li 标签
       };
   }

####4.最好的方法自然是ES规范里的东西,利用ES6新标签let来解决上面问题

 var Lis = document.getElementsByTagName('li');
   // 很简单只需要把var 改成let就行了,这是i就认为是一个局部块级作用域
  // 这种方法虽然简单,但是ES6浏览器还没有被普遍支持,所以我们一般用Babel对它进行转译后才能使用。
   for ( let i = 0; i < Lis.length; i++) {
       Lis[i].onclick = function () {    
           alert(i);
       };
   }
// 温馨提示:关于let的详细用法请参考阮一峰的ES6入门,http://es6.ruanyifeng.com/

本人Github账号:https://github.com/PandaTsui

© 著作权归作者所有

PandaTsui
粉丝 7
博文 8
码字总数 3884
作品 0
昌平
程序员
私信 提问
带你一分钟理解JS闭包——通俗易懂

网上关于闭包的文章有很多,但是大多数都使用了太多专业术语,不便于理解,我在这试着用通俗一点的语言解释一下何为闭包。 什么是闭包? 什么是闭包?闭包是什么? 先来看一段代码: functi...

爱编程的妹子
2018/11/08
0
0
理解JavaScript 闭包

几个概念 执行环境 JavaScript的解释器每次开始执行一个函数时,都会为那个函数创建一个执行环境。该环境的作用就是定义调用对象(call object)。 词法作用域和作用域链 JavaScript中,变量的...

鲜卑小兵
2013/05/27
177
1
深入理解闭包之前置知识→作用域与词法作用域

前言 这两天刚好和朋友讨论到闭包,这个JavaScript中的“神兽”,很多同学会觉得闭包这玩意太闹心了,怎么着都理解不了...其实刚接触JavaScript的时候我也是这样的。 但是呢,闭包却非常重要...

lce_shou
2018/05/16
0
0
JavaScript面向对象程序设计(7): 闭包

闭包这个概念看上去很深奥,这个词在离散数学里面的意思确实比较难于理解。在这里,我们先可以把闭包理解成是一种匿名函数或者匿名类。 1. 什么是闭包? 什么是闭包?一种正式的解释是:所谓...

迷你芊宝宝
2018/07/02
6
0
深入理解闭包之前置知识---作用域与词法作用域

前言 这两天刚好和朋友讨论到闭包,这个JavaScript中的“神兽”,很多同学会觉得闭包这玩意太闹心了,怎么着都理解不了...其实刚接触JavaScript的时候我也是这样的。 但是呢,闭包却非常重要...

iceman_dev
2018/05/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 早上儿子问我他是怎么来的

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @凉小生 :#今日歌曲推荐# 少点戾气,愿你和这个世界温柔以待。中岛美嘉的单曲《僕が死のうと思ったのは (曾经我也想过一了百了)》 《僕が死の...

小小编辑
今天
323
5
Excption与Error包结构,OOM 你遇到过哪些情况,SOF 你遇到过哪些情况

Throwable 是 Java 中所有错误与异常的超类,Throwable 包含两个子类,Error 与 Exception 。用于指示发生了异常情况。 Java 抛出的 Throwable 可以分成三种类型。 被检查异常(checked Exc...

Garphy
今天
11
0
计算机实现原理专题--二进制减法器(二)

在计算机实现原理专题--二进制减法器(一)中说明了基本原理,现准备说明如何来实现。 首先第一步255-b运算相当于对b进行按位取反,因此可将8个非门组成如下图的形式: 由于每次做减法时,我...

FAT_mt
昨天
6
0
好程序员大数据学习路线分享函数+map映射+元祖

好程序员大数据学习路线分享函数+map映射+元祖,大数据各个平台上的语言实现 hadoop 由java实现,2003年至今,三大块:数据处理,数据存储,数据计算 存储: hbase --> 数据成表 处理: hive --> 数...

好程序员官方
昨天
7
0
tabel 中含有复选框的列 数据理解

1、el-ui中实现某一列为复选框 实现多选非常简单: 手动添加一个el-table-column,设type属性为selction即可; 2、@selection-change事件:选项发生勾选状态变化时触发该事件 <el-table @sel...

everthing
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部