Javascript高级编程学习笔记(24)—— 函数表达式(2)闭包
昨天的文章中主要记录了,函数表达式与函数声明的区别
以及在JS中如何安全地使用递归
那么既然要深入地理解JS中的函数,闭包就是一个绕不开的概念
闭包
JS高编一书中对闭包的概念定义如下:
闭包是指有权访问另一个函数作用域中变量的函数
我们来理解这句话,闭包指的是一类函数
这类函数的特点是可以访问另一个函数的作用域
我们知道JS中Es6以下是没有块级作用域的
只有全局作用域,以及函数作用域
一般来讲,函数作用域里面的变量在函数外部是无法访问的
而闭包却可以访问另一个函数作用域,那么说明了什么?
说明闭包说白了就是在函数内部定义或声明的函数
以下面的代码举例
function createComparisonFunction(propertyName){// 用于创建比较函数的函数
return function(object1,object2){// 根据propertyName来比较对象的对应属性的值
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if(value1>value2){
return 1;
}else if(value1<value2){
return -1;
}else{
return 0;
}
}
}
这就是闭包的使用场景之一
我们在内部的函数中访问了外部函数的变量
而当内部匿名函数作为值返回后我们在函数的外部也能访问到函数createComparisonFunction内部的值
这样的结果似乎跟我们之前对JS的认知产生了冲突
我们知道当一个函数执行完毕后,其执行上下文便会被销毁
为其分配的内存也会被垃圾收集器回收
那么为什么闭包依旧可以访问呢?
之前我们讲过JS中的垃圾回收机制
当一个对象不再被引用时才会被垃圾收集器释放内存
而JS中的执行上下文,在ES5被称为活动对象,ES6中似乎被称为变量环境
不管名字是什么,其实就是指的一个保存变量声明等相关信息的对象
虽然 createComparisonFunction 已经执行完毕,但是由于其内部的匿名函数仍旧保存着对这个对象的引用,所以该对象无法被回收
这也是闭包占用内存多的原因
那么闭包的引用的这个对象什么时候会被回收呢?
var compareName = createComparisonFunction('name');
// compareName 保存了对返回的匿名函数的引用
// 一些操作
compareName = null;// 解除对返回的比较函数的引用
也就是当这个闭包不再被引用,闭包的执行上下文,与其外部函数的执行上下文都将一起被回收
闭包与变量
闭包虽然可以访问外部函数的值
但是其作用不是万能的,因为闭包引用的是外部函数的执行上下文
所以闭包只能获得闭包执行时的外部函数执行上下文中变量的最后一个值
function createFunctions(){
var result = new Array();
for (var i=0;i<10;i++){
result.push(function(){return i;})
}
return result;
}
在浏览器中运行结果如下

按照我们上面的结果来看,肯定是不符合我们的预期的
我们或许希望,array 数组中每个对象都返回对应执行时的值
那么我们可以通过JS中的参数传递都是值传递来完成这一点
将之前的函数改写为
function createFunctions(){
var result = new Array();
for (var i=0;i<10;i++){
result.push((function(num){
return function(){return num;}
})(i));
}
return result;
}
使用自执行函数来将每次循环的i值保存到不同的执行上下文中
我们来看看结果

这种方法相当于就是创建了十个执行上下文,每个返回的闭包都引用不同上下文,来实现的
所以十分耗费内存,在实践中不推荐使用
关于this对象
要注意的是,虽然闭包可以访问外部函数的执行上下文
但是并不意味着闭包可以直接访问外部函数的 this 和 arguments对象
因为每个函数在创建时都会自动地取得这两个变量,而不会去获取外部的this
所以如果希望在闭包中访问外部函数的this变量,那么需要在外部函数中创建一个变量来保存 this
内存泄漏
我们知道js的内存是由JS自己回收的
所以我们在获得便利的同时,也增加了内存泄漏的风险
因为这是我们不能控制的
我们只能尽量避免这种情况的发生
而跟闭包有关的主要是在DOM事件中,这里就先不展开讲了,感兴趣的小伙伴可以留言,给我说不定可以开个番外篇
Javascript高级编程学习笔记(24)—— 函数表达式(2)闭包的更多相关文章
- Javascript高级编程学习笔记(25)—— 函数表达式(3)模仿块级作用域
昨天写了闭包 今天就来聊聊块级作用域的事情 在绝大多数编程语言中,都有块级作用域这个概念 什么是块级作用域呢? 前面我们在刚开始讲的时候说过,JS中的大括号(不在赋值运算符的后面)表示代码块 块级作用 ...
- Javascript高级编程学习笔记(23)—— 函数表达式(1)递归
前面的文章中,我在介绍JS中引用类型的时候提过,JS中函数有两种定义方式 第一种是声明函数,即使用function关键字来声明 第二种就是使用函数表达式,将函数以表达式的形式赋值给一个变量,这个变量就 ...
- Javascript高级编程学习笔记(26)—— 函数表达式(4)私有变量
私有变量 严格来讲,JS中没有私有成员的概念,所有对象属性都是公有的. 但是JS中有私有变量的概念 所有在函数中定义的变量都可以认为是私有变量,因为不能在函数外部进行访问 私有变量包括 1.函数参数 ...
- 《JavaScript高级程序设计》笔记:函数表达式(七)
递归 function factorial(num){ if(num<=1){ return 1; }else { return num * arguments.callee(num-1); } ...
- Javascript高级编程学习笔记(16)—— 引用类型(5) Function类型
JS中许多有趣的地方都和函数脱不了联系 那么是什么让JS中的函数这么有趣呢? 我们一起来看看吧 Function类型 在JS中函数实际上就是对象,每个函数都是Function类型的实例,和JS的其他引 ...
- Javascript高级编程学习笔记(7)—— 函数
前几天有事耽搁了,今天继续更新 今天的主要内容是JS中的函数 这一篇主要讲函数的定义等内容,至于变量提升.执行环境.闭包.内存回收等内容在后面讲,高玩们可以不用看下面的正文了. 函数 首先来讲,函数对 ...
- JavaScript高级编程学习笔记(第三章之一)
继续记笔记,JavaScript越来越有意思了. 继续... 第三章:JavaScript基础 ECMAScript语法在很大程度上借鉴了C和其它类似于C的语言,比如Java和Perl. 大小写敏感: ...
- Javascript高级编程学习笔记(6)—— 流程控制语句
话不多说,我们直接开始进入今天的主题 流程控制语句 首先什么是流程控制语句呢? 顾名思义,就是控制流程的语句. 在JS中语句定义了ECMAScript中的主要语法,让我们可以使用一系列的关键字来完成指 ...
- Javascript高级编程学习笔记(3)—— JS中的数据类型(1)
前一段时间由于事情比较多,所以笔记耽搁了一段时间,从这一篇开始我会尽快写完这个系列. 文章中有什么不足之处,还望各位大佬指出. JS中的数据类型 上一篇中我写了有关JS引入的Script标签相关的东西 ...
随机推荐
- IIS发布MVC ASP.NET网站
发布网站后,发现无法访问,最后在配置文件上添加一段: <system.codedom> <compilers> <compiler language="c#;c ...
- 使用CSV控件方法实现参数化
一.录制脚本 二.下面介绍如何使用CSV控件方法实现参数化 1. 添加-->配置元件-->csv Data Set Config Filename:文件的来源 Variable Name ...
- propertychange事件导致的IE浏览器堆栈溢出
前段事件做项目,在IE下测试时,发现会报堆栈溢出的错误,其他浏览器正常,于是开始了苦逼的IE查错路程... 由于是在操作了某个输入框之后才出现的错误,所以把重点放到了input的相关事件,最终发现是这 ...
- js 内置对象参考 (Array,String, Math, Data, Number)
var str = "helloWorld"; var strOne = "helloWorld"; // charAt() 返回在指定位置的字符. var a ...
- TCP/IP数据加密传输及CA简述
TCP/IP跨主机之间的通信数据封装发送的都是明文数据,现代通讯中会有安全问题. 三个安全问题 如:A发送消息给B的三个安全问题机密性:明文传输如:ftp,http,smtp,telnet等完整性:数 ...
- 线程池ThreadPoolExecutor源码分析
在阿里编程规约中关于线程池强制了两点,如下: [强制]线程资源必须通过线程池提供,不允许在应用中自行显式创建线程.说明:使用线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销,解决资源 ...
- PPS--在download DN出现的问题注意:
1,DN的下载条件:(没有删除没有下载) PPSL=’N’(PPSL有两个值,N时是指这个DN还没有下载) DEL_FLAG<>’Y’(DEL_FLAG有两个值,Y时说明已经删除,不会下载 ...
- target = e.target || e.srcElement(转载)
//鼠标点击出现下拉菜单,点其他地方,缩回去. document.addEventListener("mousedown", function(e) { var target = ...
- 第二阶段第八次spring会议
昨天我对软件进行了植物网站的添加. 今天我将对软件进行宠物信息的添加. 清屏功能 private void button5_Click(object sender, EventArgs e) { te ...
- PM学习梳理--搭建产品架构