Javascript学习笔记之 函数篇(三) : 闭包和引用


Posted in Javascript onNovember 23, 2014

Javascript 中一个最重要的特性就是闭包的使用。因为闭包的使用,当前作用域总可以访问外部的作用域。因为 Javascript 没有块级作用域,只有函数作用域,所以闭包的使用与函数是紧密相关的。

模拟私有变量

function Counter(start) {

    var count = start;

    return {

        increment: function() {

            count++;

        },

        get: function() {

            return count;

        }

    }

}

var foo = Counter(4);

foo.increment();

foo.get(); // 5

这里 Counter 返回两个闭包:函数 increment 和 get。这两个函数一直保持着对 Counter 作用域的访问,因此它们能一直访问到定义在 Counter 作用域的变量 count。

私有变量的工作机制

由于 Javascript 不可以对作用域赋值和引用,所以在上例中,是没有办法在外部直接访问内部私有变量 count。唯一的方法就是通过定义闭包来访问。

var foo = new Counter(4);

foo.hack = function() {

    count = 1337;

};

上面的代码不会改变 Counter 作用域内的 count 变量值,因为 hack 没有在 Counter 内定义。上面这段代码只会创建或者覆盖全局变量 count。

循环内的闭包

一个最容易犯的错误就是在循环内使用闭包。

for(var i = 0; i < 10; i++) {

    setTimeout(function() {

        console.log(i);  

    }, 1000);

}

上面这段代码不会输出0到9,而是连续输出10次10。
上面的匿名会一直保持一个对变量 i 的引用。当调用 console.log 函数开始输出时,这是循环已经结束,而变量 i 已经为10了。
为了避免上面的错误发生,我们需要在每次循环时为变量 i 值创建一个拷贝。

避免引用错误

为了复制循环中变量的值,最好的方式是在外层加一个匿名的立刻执行函数。

for(var i = 0; i < 10; i++) {

    (function(e) {

        setTimeout(function() {

            console.log(e);  

        }, 1000);

    })(i);

}

这个外部的匿名函数接收循环变量 i 作为第一个参数,并将其值拷贝至它自身的参数 e。
外部的匿名函数将参数 e 再传递给 setTimeout,因此 setTimeout 有了指向参数 e 的引用。而且这个参数 e 的值不会因为外部的循环改变而改变。

还有另外一个方法可以实现同样的效果,就是在 setTimeout 内的匿名函数中再返回一个匿名函数:

for(var i = 0; i < 10; i++) {

    setTimeout((function(e) {

        return function() {

            console.log(e);

        }

    })(i), 1000)

}

此外,通过 bind 方法也可以实现。

for(var i = 0; i < 10; i++) {

    setTimeout(console.log.bind(console, i), 1000);

}

文章最后我们来总结下:

(1)闭包是一种设计原则,它通过分析上下文,来简化用户的调用,让用户在不知晓的情况下,达到他的目的;
(2)网上主流的对闭包剖析的文章实际上是和闭包原则反向而驰的,如果需要知道闭包细节才能用好的话,这个闭包是设计失败的;
(3)尽量少学习。

Javascript 相关文章推荐
js jquery做的图片连续滚动代码
Jan 06 Javascript
JavaScript 闭包深入理解(closure)
May 27 Javascript
javascript 操作Word和Excel的实现代码
Oct 26 Javascript
Jquery Ajax 学习实例2 向页面发出请求 返回JSon格式数据
Mar 15 Javascript
jquery创建表格(自动增加表格)代码分享
Dec 25 Javascript
jquery操作cookie插件分享
Jan 14 Javascript
简单的ajax连接库分享(不用jquery的ajax)
Jan 19 Javascript
jquery删除数据记录时的弹出提示效果
May 06 Javascript
React-router v4 路由配置方法小结
Aug 08 Javascript
Angularjs Promise实例详解
Mar 15 Javascript
bootstrap table实现iview固定列的效果实例代码详解
Sep 30 Javascript
Vue scoped及deep使用方法解析
Aug 01 Javascript
js实例属性和原型属性示例详解
Nov 23 #Javascript
JS常用函数使用指南
Nov 23 #Javascript
浅谈JSON和JSONP区别及jQuery的ajax jsonp的使用
Nov 23 #Javascript
理解jQuery stop()方法
Nov 21 #Javascript
JS中三目运算符和if else的区别分析与示例
Nov 21 #Javascript
node.js使用npm 安装插件时提示install Error: ENOENT报错的解决方法
Nov 20 #Javascript
JS在可编辑的div中的光标位置插入内容的方法
Nov 20 #Javascript
You might like
探讨:如何编写PHP扩展
2013/06/13 PHP
Destoon旺旺无法正常显示,点击提示“会员名不存在”的解决办法
2014/06/21 PHP
地震发生中逃生十大法则
2008/05/12 Javascript
javascript full screen 全屏显示页面元素的方法
2013/09/27 Javascript
jQuery之过滤元素操作小结
2013/11/30 Javascript
javascript实现简单的进度条
2015/07/02 Javascript
JS实现选项卡实例详解
2015/11/17 Javascript
jQuery实现表格行和列的动态添加与删除方法【测试可用】
2016/08/01 Javascript
jQuery简单实现页面元素置顶时悬浮效果示例
2016/08/01 Javascript
javascript实现圣旨卷轴展开效果(代码分享)
2017/03/23 Javascript
老生常谈combobox和combotree模糊查询
2017/04/17 Javascript
vue cli构建的项目中请求代理与项目打包问题
2018/02/26 Javascript
常用的 JS 排序算法 整理版
2018/04/05 Javascript
微信小程序表单验证form提交错误提示效果
2020/06/19 Javascript
java实现单链表增删改查的实例代码详解
2019/08/30 Javascript
基于layui的下拉列表的数据回显方法
2019/09/24 Javascript
js屏蔽F12审查元素,禁止修改页面代码等实现代码
2020/10/02 Javascript
[49:15]DOTA2-DPC中国联赛 正赛 CDEC vs XG BO3 第二场 1月19日
2021/03/11 DOTA
python处理中文编码和判断编码示例
2014/02/26 Python
基于进程内通讯的python聊天室实现方法
2015/06/28 Python
Python编程实现及时获取新邮件的方法示例
2017/08/10 Python
Python 2.x如何设置命令执行的超时时间实例
2017/10/19 Python
对pandas中两种数据类型Series和DataFrame的区别详解
2018/11/12 Python
使用Python和Prometheus跟踪天气的使用方法
2019/05/06 Python
Python 自动登录淘宝并保存登录信息的方法
2019/09/04 Python
Python实现队列的方法示例小结【数组,链表】
2020/02/22 Python
意大利自行车商店:Cingolani Bike Shop
2019/09/03 全球购物
物业管理计划书
2014/01/10 职场文书
开业典礼主持词
2014/03/21 职场文书
成立公司计划书
2014/05/07 职场文书
垃圾桶标语
2014/06/24 职场文书
基层党组织建设整改方案
2014/09/16 职场文书
2014年副班长工作总结
2014/12/10 职场文书
贫民窟的百万富翁观后感
2015/06/09 职场文书
用人单位的规章制度,怎样制定才是有效的?
2019/07/09 职场文书
浅谈哪个Python库才最适合做数据可视化
2021/06/28 Python