JavaScript使用闭包模仿块级作用域操作示例


Posted in Javascript onJanuary 21, 2019

本文实例讲述了JavaScript使用闭包模仿块级作用域操作。分享给大家供大家参考,具体如下:

在阅读这篇文章之前,建议先阅读JavaScript的作用域链以及JavaScript闭包。

正如闭包的定义一样:“闭包指的是有权访问另一个函数作用域中的变量的函数”, 闭包最大的意义就在于闭包可以对另一个函数作用域的变量进行访问,由此,闭包可以延伸出一系列的用法。

模仿块级作用域

JavaScript没有块级作用域的概念。这意味着在块语句中定义的变量,实际上是包含在函数中而非语句中创建的。从作用域链的角度来理解是,所有在函数内定义的变量(所有,也就是说块语句中定义的变量也包含在内)都会在这个函数执行时所创建的函数的活动对象中,因此从函数内的所有变量定义开始,就可以在函数内部随处访问它,闭包也可以通过作用域链访问它。
例子:

function outputNumbers(count){
  for(var i = 0; i < count; i++){
    console.log(i); // 0, 1, ... count - 1
  }
  console.log(i); // count
}

C++, JAVA等语言中,变量i只会在for循环的语句块(block)中有定义,循环一旦结束,变量i就会被销毁。可是在JavaScript中,变量i是定义在outputNumbers()的活动对象中,因此从函数内的所有变量定义开始,就可以在函数内部随处访问它,闭包也可以通过作用域链访问它。即使像下面这样重新声明同一个变量,也不会改变它的值。

function outputNumbers(count){
  for(var i = 0; i < count; i++){
    console.log(i); // 0, 1, ... count - 1
  }
  var i;     // redeclare i
  console.log(i); // count
}

JavaScript从来不管是否多次声明了同一个变量;遇到这种情况,JavaScript只会对后续的声明视而不见(不过会执行后续声明中的变量初始化),将其当成一个赋值语句。

函数包装器可以用来模仿块作用域并避免这个问题。

函数包装器就是创建并立即调用一个函数。

(function(){
  console.log("Hello World!");
})();

这段代码直接输出”Hello World”, 这就是一个函数包装器。

函数包装器的作用:

1. 立即执行函数中的代码,又不会再内存中留下对该函数的引用;

2. 函数内部的所有变量都会被立即销毁(除非将这些变量赋值给了包含作用域中的变量)。

当在函数内部使用函数包装器的时候,此时函数包装器就是一个闭包,有权访问外部环境中的所有变量。

function outputNumbers(count){
  (function(){
    //块级作用域
    for(var i = 0; i < count; i++){
      console.log(i); // 0, 1, ... count - 1
    }
  })();
  console.log(i); // error
}

在函数包装器中可以访问外部环境outputNumbers()的变量count,打印0, 1, … count - 1,但是在函数包装器执行完毕之后,再访问变量i就会抛出错误,因为i是在函数包装器中定义的,outputNumbers()函数无法访问。

无论在什么地方,如果只需要一些临时变量,就可以使用块级作用域!

使用函数包装器这种闭包可以减少闭包过多占用内存的问题。因为没有指向匿名函数的引用, 所以只要函数包装器执行完毕,就可以立即销毁其作用域链了。

函数包装器这种技术经常在全局作用域中被用在函数外部,从而限制想全局作用域中添加过多的变量和函数。一般来说,我们都应该尽量少向全局作用域中添加变量和函数。过多的全局变量和函数很容易导致命名冲突。通过创建块级作用域,每个开发人员既可以使用自己的变量,有不必担心搞乱全局作用域。例如:

(function(){
  var now = new Date();
  if (now.getMonth() == 0 && now.getDate() == 1) {
    console.log("Happy new year");
  }
})();

将这段代码放在全局作用域中,可以用来确定哪天是一月一日。其中变量now现在是匿名函数中的局部变量,避免了在全局变量中创建。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
JS控制文本框textarea输入字数限制的方法
Jun 17 Javascript
js 判断图片是否加载完以及实现图片的预下载
Aug 14 Javascript
JS获取当前脚本文件的绝对路径
Mar 02 Javascript
javascript实现简单的on事件绑定
Aug 23 Javascript
用director.js实现前端路由使用实例
Jan 27 Javascript
页面间固定参数,通过cookie传值的实现方法
May 31 Javascript
vue2.0移除或更改的一些东西(移除index key)
Aug 28 Javascript
浅谈如何使用 webpack 优化资源
Oct 20 Javascript
Vue项目组件化工程开发实践方案
Jan 09 Javascript
vue、react等单页面项目部署到服务器的方法及vue和react的区别
Sep 29 Javascript
JavaScript从原型到原型链深入理解
Jun 03 Javascript
在vue中使用Echarts画曲线图的示例
Oct 03 Javascript
JavaScript闭包与作用域链实例分析
Jan 21 #Javascript
js中事件对象和事件委托的介绍
Jan 21 #Javascript
JavaScript作用域链实例详解
Jan 21 #Javascript
Jquery的Ajax技术使用方法
Jan 21 #jQuery
js变量声明var使用与不使用的区别详解
Jan 21 #Javascript
Vue中Axios从远程/后台读取数据
Jan 21 #Javascript
vue项目中实现的微信分享功能示例
Jan 21 #Javascript
You might like
15个小时----从修改程序到自己些程序
2006/10/09 PHP
PHP 批量删除 sql语句
2009/06/05 PHP
PHP中创建空文件的代码[file_put_contents vs touch]
2012/01/20 PHP
PHP命名空间(namespace)的动态访问及使用技巧
2014/08/18 PHP
php把字符串指定字符分割成数组的方法
2018/03/12 PHP
Aster vs KG BO3 第三场2.18
2021/03/10 DOTA
CheckBox 如何实现全选?
2006/06/23 Javascript
在页面上点击任一链接时触发一个事件的代码
2007/04/07 Javascript
jquery 列表双向选择器之改进版
2013/08/09 Javascript
利用js实现在浏览器状态栏显示访问者在本页停留的时间
2013/12/29 Javascript
js实现的倒计时按钮实例
2015/06/24 Javascript
jQuery实现控制文字内容溢出用省略号(…)表示的方法
2016/02/26 Javascript
微信公众平台开发教程(五)详解自定义菜单
2016/12/02 Javascript
jQuery Validate让普通按钮触发表单验证的方法
2016/12/15 Javascript
jquery uploadify如何取消已上传成功文件
2017/02/08 Javascript
浅谈Angular4实现热加载开发旅程
2017/09/08 Javascript
使用Object.defineProperty如何巧妙找到修改某个变量的准确代码位置
2018/11/02 Javascript
vue中实现上传文件给后台实例详解
2019/08/22 Javascript
Python内置函数OCT详解
2016/11/09 Python
基于循环神经网络(RNN)的古诗生成器
2018/03/26 Python
django框架F&amp;Q 聚合与分组操作示例
2019/12/12 Python
使用OpenCV实现道路车辆计数的使用方法
2020/07/15 Python
CSS3制作翻转效果_动力节点Java学院整理
2017/07/11 HTML / CSS
泰国Robinson百货官网:购买知名品牌的商品
2020/02/08 全球购物
远程调用的原理
2014/07/05 面试题
简历中自我评价分享
2013/10/09 职场文书
高中生班主任评语
2014/04/25 职场文书
2014年六一儿童节演讲稿
2014/05/23 职场文书
文秘专业应届生求职信
2014/05/26 职场文书
建筑安全标语
2014/06/07 职场文书
学校党的群众路线教育实践活动个人整改方案
2014/10/31 职场文书
聋哑人盗窃罪辩护词
2015/05/21 职场文书
培训简讯范文
2015/07/20 职场文书
Springboot配置suffix指定mvc视图的后缀方法
2021/07/03 Java/Android
Redis中一个String类型引发的惨案
2021/07/25 Redis
24年收藏2000多部退役军用电台
2022/02/18 无线电