Js中的闭包入门攻略_闭包菜鸟知识

闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式就是在一个函数内部创建另一个函数。来看下面的示例:function createFn(name){return function(obj){return obj[name];}
}var ageGetFn = createFn(‘bob’);
var age = ageGetFn({bob:

Js中的闭包入门攻略

闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式就是在一个函数内部创建另一个函数。来看下面的示例:

Js中的闭包入门攻略_闭包菜鸟知识

function createFn(name){
  return function(obj){
    return obj[name];
  }
}

var ageGetFn = createFn('bob');
var age = ageGetFn({bob: 18, jack: 20});
console.log(age);// 18

createFn返回了一个匿名函数,该匿名函数访问了createFn的参数name。

使用ageGetFn接收createFn的返回值,从表面上来看,createFn执行结束后就应该被销毁了。当调用ageGetFn时不应该还能访问到createFn的name参数,但事实情况是访问到了,就好像name已经和ageGetFn绑定在一起了一样。那么ageGetFn到底是通过什么机制访问的呢?

我们知道在JavaScript中作用域分为全局作用域和局部作用域,全局作用域对应window全局变量对象,局部作用域指的就是函数作用域,对应的是函数的变量对象。

当采用闭包时,会将外部函数的变量对象加入内部函数的作用域链中,如下图在浏览器中显示的一样: 

Js中的闭包入门攻略_闭包菜鸟知识

当createFn(‘bob’)运行结束后,createFn的作用域被销毁,但是其变量对象被加入到了ageGetFn的作用域链中,没有被销毁。因此根据作用域链搜索机制,ageGetFn可以访问到createFn中的name参数。

但也正是因为闭包会携带包含它的函数的变量对象,因此会比其他函数占用更多的内存。过度使用闭包可能会导致内存占用过多,建议读者只在绝对必要时再考虑使用闭包。虽然V8等优化后的JavaScript引擎会尝试回收被闭包占用的内存,但请大家还是要慎用闭包。

在上例中,当ageGetFn执行结束后,也可以加上一句ageGetFn = null,这样可以通知垃圾回收例程尽快将其清除,以便释放内存。

另外需要说明的是,作用域链的这种配置机制使得闭包只能取得外部函数中变量的最后一个值,什么意思呢?看下面的示例:

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

乍一看,arrFn中的每个函数都应该返回该函数在数组中的脚标,即位置0的函数返回0,位置1的函数返回1,依次类推,但事实上每个函数都返回3,为什么呢?看下图: 

Js中的闭包入门攻略_闭包菜鸟知识

arrFn中的每个函数的作用域链中都保存着createFn的变量对象,而当createFn运行结束后,其变量对象中的i为3,因此arrFn中每个函数的返回值都为3。那么有没有方法修正呢?当然是有的,还是使用闭包,看下面示例:

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

arrFn中的每个函数都是一个立即执行函数的返回值,这样每个函数中的num就是每个立即执行函数的变量对象的num,而每个立即执行函数执行时,都接收特定的i作为参数,故而每个立即执行函数的变量对象的num都是特定的值,不会受到createFn中最后i的影响。如下图所示: 

Js中的闭包入门攻略_闭包菜鸟知识

海计划公众号
(0)
上一篇 2020/03/30 16:07
下一篇 2020/03/30 16:07

您可能感兴趣的内容

  • 弹性(Flex)布局的使用小白攻略_布局使用攻略

    最近我参与实施的两个项目中,一个页面交互复杂,而另一个相对传统,两个项目相比之下凸显出了页面布局样式的时间占比不可忽视,使用了弹性布局代码量精简了不少。虽说如此,弹性布局往往会有些潜在的问题,且改动后,要立即查看页面也需要不少时间,因此我把项目中使用弹性布局过程中遇到的问题稍作整理,为大家以后使用时,可以有效规避这些麻烦。 使用场景前端开发中,网页布局是很重

    2020/03/20
  • lazysizes.js小白入门响应式图像延迟加载JS插件【懒加载】

    lazysizes.js基础入门 官方网址:http://afarkas.github.io/lazysizes/#examples GitHub:https://github.c…

    2020/03/05
  • 快递员凌晨送件,将下班程序员误认成小偷基础知识教程_程序员菜鸟教程

    近日,杭州一位快递员深夜前往某小区送快递,却把深夜下班程序员误认为“小偷”的视频,在社交媒体上引发了关注。在小区道路上,一男子蹲在一辆电动车前捣鼓着车座,电动车的前座还绑着好几个快递箱。快递员走上前,拦住该男子的电瓶车车把,与其进行语言上的沟通,现场两人发生了轻微的肢体拉扯。据了解,快递员小哥叫小董,是天猫直送负责配送该片区的快递员。11 月 11 日当天的

    2020/04/03
  • Flutter Kotlin 到底该如何选择?小白知识_Flutter使用攻略

    1. 我的选择这两个技术在当下如何选择,我之前在公众号上的回复是:1. 如果你已经处于一个比较满意的公司,并考虑长期发展,公司并未使用这两个技术,你可以专心钻研公司当下使用的,或者未来将要使用的,这些才能助你在公司步步高升。2. 如果你考虑换工作,且已经有目标公司,那可以看这个目标公司,目标部门的招聘,或者看他们对外的分享,如果有注重Flutter或者Kot

    2020/03/29
  • node-sass是什么?入门指南_sass使用攻略

    Node-sass是一个库,它将Node.js绑定到LibSass(流行样式表预处理器Sass的C版本)。它允许用户以令人难以置信的速度将.scss文件本地编译为css,并通过连接中间件自动编译。什么是Sass?Sass是一种预处理器脚本语言,可以解释或编译成层叠样式表(CSS)。Sass包含两种语法:较旧的语法使用缩进将代码块和换行符分隔为单独的规则;较新

    2020/03/31
  • h5本地预览上传的图片或视频菜鸟教程下载_图片指南攻略

    通过 中的change事件 拿到的file不能直接在本地预览选择的图片或者视频,可以通过以下两种方式预览本地图片,不用上传到服务器就可以本地预览。createObjectURL这种方式生成的文件地址可以预览图片和视频
    <h

    2020/03/29
  • h5中的结构元素header、nav、article、aside、section、footer介绍入门教程_元素小白帮助

    结构元素不具有任何样式,只是使页面元素的的语义更加明确。header元素header元素是一种具有引导和导航作用的的结构元素,该元素可以包含所有通常放在页面头部的内容。header元素通常用来放置整个页面或页面内的一个内容区块的标题,也可以包含网站Logo图片、搜索表单或者其他相关内容。

    网页主题

    一个网页中

    2020/03/24
  • vim-web:像 IDE 一样的 Vim,安装配置自己的 Vim攻略教程_IDE小白指南

    在 vim-web v2 版本插件配置太多,新版本 v3 只配置少量的插件,是一个简单的版本。安装最新版本的Vim 8.1+ 使用下面命令安装 vim 版本并更新:brew install macvim # 安装 macvim
    brew install macvim –override-system-vim将插件以及配置下载到 ~/.vim/ 目录中,这个

    2020/03/29
  • HackerRank小白基础_编码难题为基础的新兴的社交平台

    HackerRank小白基础 官方网址:https://www.hackerrank.com/ 简介描述:编码难题为基础的新兴的社交平台 HackerRank网站,为编码程序员们提…

    2020/03/06
  • 设计师常用的几个资源网站分享小白攻略_设计小白知识

    如果你是一名设计师,你的电脑上可能存储了很多的设计网站,但是对于一些新手小白来说,刚接触设计的时候应该怎样进行绘制呢?难道要自己去一笔一笔的进行绘制吗?下面给大家分享几个设计网站,一起来看看吧!1.美图秀秀网页版美图秀秀很好用,这个美图秀秀的网页版一样好用!网页的设置比起客户端来说简洁很多,不过基础工具并不没有被阉割,那些备受网友好评的功能,比如批量图片裁剪

    2020/03/26
  • CSS 标签的分类,及显示模式菜鸟教程网_标签菜鸟教程网

    标签的类型(显示模式) HTML标签一般分为块标签和行内标签两种类型,它们也称块元素和行内元素。一、块级元素(block-level)每个块元素通常都会独自占据一整行或多整行,可以对其设置宽度、高度、对齐等属性,常用于网页布局和网页结构的搭建。常见的块元素有

    ~

    、、

      1. 等,其中 标签是最典型
    2020/03/29
  • hyperHTML基础教程_一个快速和轻量级的虚拟DOM替代方案

    hyperHTML基础教程 GitHub:https://github.com/WebReflection/hyperHTML 简介描述:一个快速和轻量级的虚拟DOM替代方案 一个…

    2020/03/07
  • 365psd新手入门_免费的 PSD、图形和矢量文件

    365psd新手入门 官方网址:https://365psd.com/

    2020/03/06
  • Sass 简介使用攻略_Sass小白攻略

    概念Sass由hampton catlin设计,natalie weizenbaum于2006年开发,它可以免费下载和使用。Sass是一个将脚本解析成CSS的脚本语言(SassScript),也是一款CSS预处理器,它减少了CSS的重复,也因此节省了时间。Sass 是对CSS3(层叠样式表)的语法的一种扩充 Sass ,扩展了 CSS3,增加了规则、变量、混

    2020/03/23
  • day.js轻量级处理时间和日期格式化库小白攻略_库小白知识

    Day.js是一个轻量的处理时间和日期的JavaScript库,和Moment.js的API设计保持完全一样. 如果您曾经用过Moment.js, 那么您已经知道如何使用Day.js。 Day.js的特点有:和 Moment.js 相同的 API 和用法不可变数据 (Immutable)支持链式操作 (Chainable)国际化 I18n仅 2kb 大小的微

    2020/03/23
  • 关于CSS自文档的思考使用指南css声明式语言式代码注释_css小白攻略

    原文出处 Thoughts on Self-Documenting CSS作者:Keith J. Grant,翻译来源:http://www.zcfy.ccRobert C. Martin写的《Clean Code》是我读过的最好的编程书籍之一,若没有读过,推荐你将它加入书单。注释就意味着代码无法自说明 —— Robert C. MartinMartin在文

    2020/04/05