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 相关文章推荐
jQuery编写widget的一些技巧分享
Oct 28 Javascript
JavaScript.The.Good.Parts阅读笔记(二)作用域&amp;闭包&amp;减缓全局空间污染
Nov 16 Javascript
Javascript核心读书有感之类型、值和变量
Feb 11 Javascript
JQuery自动触发事件的方法
Jun 13 Javascript
jQuery实现美观的多级动画效果菜单代码
Sep 06 Javascript
解决JS内存泄露之js对象和dom对象互相引用问题
Jun 25 Javascript
移动端效果之Swiper详解
Oct 09 Javascript
jQuery实现table表格信息的展开和缩小功能示例
Jul 21 jQuery
浅析JS中什么是自定义react数据验证组件
Oct 19 Javascript
Windows下支持自动更新的Electron应用脚手架的方法
Dec 24 Javascript
新手简单了解vue
May 29 Javascript
JavaScript设计模式之观察者模式与发布订阅模式详解
May 07 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加密解密的代码
2007/07/16 PHP
PHP数组排序之sort、asort与ksort用法实例
2014/09/08 PHP
PHP addAttribute()函数讲解
2019/02/03 PHP
php设计模式之组合模式实例详解【星际争霸游戏案例】
2020/03/27 PHP
javascript 特性检测并非浏览器检测
2010/01/15 Javascript
基于jquery的页面划词搜索JS
2010/09/14 Javascript
Javascript与jQuery方法的隐藏与显示
2015/01/19 Javascript
jquery实现像栅栏一样左右滑出式二级菜单效果代码
2015/08/24 Javascript
全面了解JavaScirpt 的垃圾(garbage collection)回收机制
2016/07/11 Javascript
JS编写函数实现对身份证号码最后一位的验证功能
2016/12/29 Javascript
Bootstrap Tree View简单而优雅的树结构组件实例解析
2017/06/15 Javascript
JS FormData上传文件的设置方法
2017/07/05 Javascript
React-Native中props具体使用详解
2017/09/04 Javascript
jQuery图片加载失败替换默认图片方法汇总
2017/11/29 jQuery
详解vue-cli项目中的proxyTable跨域问题小结
2018/02/09 Javascript
浅谈vue方法内的方法使用this的问题
2018/09/15 Javascript
处理JavaScript值为undefined的7个小技巧
2020/07/28 Javascript
Python判断字符串是否为字母或者数字(浮点数)的多种方法
2018/08/03 Python
Windows下安装Scrapy
2018/10/17 Python
Django 解决阿里云部署同步数据库报错的问题
2020/05/14 Python
一些关于python 装饰器的个人理解
2020/08/31 Python
Prometheus开发中间件Exporter过程详解
2020/11/30 Python
用python制作个视频下载器
2021/02/01 Python
把富文本的回车转为br标签
2019/08/09 HTML / CSS
H5混合开发app如何升级的方法
2018/01/10 HTML / CSS
三只松鼠官方旗舰店:全网坚果销售第1
2017/11/25 全球购物
英国复古服装和球衣购买网站:3Retro Football
2018/07/09 全球购物
Yummie官方网站:塑身衣和衣柜必需品
2019/10/29 全球购物
写一个函数返回1+2+3+…+n的值(假定结果不会超过长整型变量的范围)
2014/09/05 面试题
电子专业毕业生自我鉴定
2014/01/22 职场文书
学习雷锋寄语大全
2014/04/11 职场文书
社团活动总结模板
2014/06/30 职场文书
小学生教师节演讲稿
2014/09/03 职场文书
2014年政工师工作总结
2014/12/18 职场文书
大学生国家助学金感谢信
2015/01/23 职场文书
学校远程教育工作总结
2015/08/11 职场文书