带有执行环境的函数 - 闭包
学习 JavaScript 的同学都会面对闭包,总觉得很难,你会看到闭包各种版本的定义,即使把闭包的概念背会也不一定的能够理解闭包。想要掌握闭包,需要看很多关于闭包的资料,加上对 JavaScript 执行过程的理解才能掌握闭包。如果你看到“一文读懂闭包”,“十分钟读懂闭包”这类文章后,想「投机取巧」花几分钟时间能够理解闭包,其实是不可能的,一切需要脚踏实地,慢慢就理解了。
「闭包的出现能给编程带来哪些便捷呢?」,这是我们学习闭包首先需要面对的问题,也就是说闭包出现的背景是什么。
函数是无状态的,比如下面的函数:
function call() {var name = 'suyan';var age = 20;console.log(name + ' age is ' + age);
}
call();
当 call 函数执行完后 name 和 age 占用的内存空间将会被释放,在函数外部无法访问变量 name 和 age 。如果想要在函数 call 外访问变量 age,且函数执行完后保留 age 的值,咋么办?
想要解决这个问题,可以使用闭包(colsure)
function call() {var name = 'suyan';var age = 20;console.log(name + ' age is ' + age);return {getAge: function () {return age;},setAge: function (newValue) {age = newValue;}};
}
const ageObj = call();
console.log(ageObj.getAge()); // 20
// 修改 age 的值为 30
ageObj.setAge(30);
console.log(ageObj.getAge()); // 30
通过 Chrome 调试工具可以查看 call 这个函数捕获的闭包中的变量:
闭包一大重要特征就是可以「保存函数执行环境中的变量」,使其延迟释放,比如下面的函数:
function createCounter() {let counter = 0;const myFunction = function() {counter = counter + 1;return counter;};return myFunction;
}
// increment 是一个函数
const increment = createCounter();
const c1 = increment();
const c2 = increment();
const c3 = increment();
console.log(c1, c2, c3); // 1,2,3
increment 这个函数使用了 createCounter 中的变量 counter,每次调用 increment 这个函数,变量 counter 一直保存在执行环境中,并不会被释放。再创建一个 increment2,这是 c11 的值为 1。可见 increment 和 increment2 使用的执行环境互不影响。
const increment2 = createCounter();
const c11 = increment2();
console.log(c11); // 1
闭包使得一个函数可以访问另一个函数作用域中的变量。我们在看一下 JavaScript 内置对象数组 这节课程中的一道关于闭包的面试题:
(function () {var numbers = [];for (var i = 0; i < 4; i++) {numbers.push(function () {return i;});}var result = numbers.map(function (e) {return e();});console.log(result); // 值是什么?
})();
最终打印的值是 4、4、4、4。在函数中通过 var 声明的变量 i 属于函数作用域,当代码执行到第 8 行后, i 的值是 4。此时 numbers 中保存为 4 个函数,当这些函数被执行的时候会使用当前函数执行环境中的变量 i,此时值为 4,故最终 result 中的值都是 4。
如果把上面代码中的 var i = 0;修改成 let i = 0;结果是什么?
总之,闭包可以延长变量的释放,你可以把闭包看做是带有执行环境的函数。
推荐阅读:
看透变量提升与块级作用域实现的原理
执行上下文与调用栈
推荐我精心准备的 JavaScript 学习资源
带有执行环境的函数 - 闭包相关推荐
- js执行环境作用域和闭包_JavaScript中执行上下文,提升,作用域和闭包的终极指南
js执行环境作用域和闭包 It may seem surprising, but in my opinion the most important and fundamental concept to ...
- 深入理解闭包系列第二篇——从执行环境角度看闭包
前面的话 本文从执行环境的角度来分析闭包,先用一张图开宗明义,然后根据图示内容对代码进行逐行说明,试图对闭包进行更直观的解释 图示 说明 下面按照代码执行流的顺序对该图示进行详细说明 function ...
- 闭包、执行环境、作用域链
闭包是指有权访问另一个函数作用域中的变量的函数,创建的常见方式就是在一个函数内部创建另一个函数. 我们来理解下执行环境和作用域链: 1.执行环境有全局执行环境和函数执行环境之分. 2.每次进入一个新的 ...
- JavaScript中的执行环境
JavaScript中的执行环境 注意区分函数的执行环境和函数声明环境 看代码: 转载于:https://www.cnblogs.com/mc67/p/5190179.html
- 作用域、执行环境、作用域链
作用域,之前有介绍过,JavaScript无块级作用域,只有函数作用域,简单点说就是JavaScript的作用域就是函数作用域.因为有函数作用域,所以我们有全局作用域和局部作用域的说法. 执行环境是什 ...
- JavaScript——执行环境、变量对象、作用域链
前言 这几天在看<javascript高级程序设计>,看到执行环境和作用域链的时候,就有些模糊了.书中还是讲的不够具体.通过上网查资料,特来总结,以备回顾和修正. 目录: EC(执行环境或 ...
- JavaScript语言精粹--执行环境及作用域,this
1.执行环境定义了变量或函数有权访问的其他数据,决定了他们各自的行为. 每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中. 虽然我们无法访问,但是解析器在处理数据时 ...
- JavaScript执行环境
执行环境(Execution Context,也称为"执行上下文")是JavaScript中最为重要的一个概念.执行环境定义了变量或函数有权访问的其它数据,决定了各自的行为.当Ja ...
- JavaScript执行环境 + 变量对象 + 作用域链 + 闭包
闭包真的是一个谈烂掉的内容.说到闭包,自然就涉及到执行环境.变量对象以及作用域链.汤姆大叔翻译的<深入理解JavaScript系列>很好,帮我解决了一直以来似懂非懂的很多问题,包括闭包.下 ...
最新文章
- 第一个python去掉行号
- Hadoop实例之利用MapReduce实现日志清洗(附源代码)
- 内容处理和分发中的算法应用探究
- Django 执行 makemigrations 显示 No changes detected in app
- Linux学习之系统编程篇:利用 shm 进行进程间通信
- 尝鲜.net core2.1 ——编写一个global tool
- 21 RadioGroup ListFragment
- LVM--逻辑卷管理
- python按月分组_python-将行按两列分组并通过比较过滤值
- 在Eclipse新建菜单中添加菜单项,其他地方添加菜单项类似
- axios, ajax和fetch的比较
- additemdecoration重复_安卓中另一个强大的大量数量集控件RecyclerView
- android中一些常用的VIEW动作类型
- Sybase ASE15.7静默安装
- 01_LBP算法原理
- Vijos P1423 最佳路线
- 卓有成效的管理者—第一章 卓有成效是可以学会的
- 嵌入式开发需要学习什么?
- centos查询 硬盘序列号查询_CentOS查看主板型号、CPU、显卡、硬盘等信息
- C++ 字元陣列(C-style)、字元指標、String類別 使用方式整理