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标签相关的东西 ...
随机推荐
- Opecv + Anaconda 读取视频(windows)
前言:之前一直用的是python(x,y),但是发现在使用opencv时容易出现一些pythonw.exe停止工作的问题.后来发现自己的操作系统是64位的,却安装了32位的python(x,y),虽然 ...
- iframe和form表单实现ajax请求上传数据
form的target属性设置为iframe的name值时,表示提交到url后返回的数据显示到iframe区域 <form action="/upload.html" met ...
- openstack 王者归来学习笔记
rpc.call方法执行的流程:(下次看代码的时候可以根据这流程来看,注意:由于rpc服务器和客户端具有很松的耦合性,因此以上步骤并不是绝对的.) 1.rpc服务器定义和启动rpc服务 2.rpc服务 ...
- HTML与盒模型
EC前端 - HTML教程 HTML与盒模型 HTML结构 <!doctype html> <html> <head> <meta charset=" ...
- Python爬虫学习--用Python结合Selenium实现 明日之子节目直播时为自己喜欢的选手自动点赞拉票!!!
声明:本脚本纯属娱乐,请勿用来非法点赞拉票,任何使用不当造成的后果自行承担. 闲话: 明日之子第二季开始好久了,作者一直再追,特别喜欢里面那个酷酷的小哥-蔡泽明.前两天晋选9大厂牌,采取的是直播的形式 ...
- [入门]在Mac OS X下使用和配置Android Studio
Android Studio可谓是安卓开发的XCode,流畅的速度+顺眼的UI足以秒杀Eclipse.在Mac OS X可以通过如下的途径获得Android Studio 最新版本的Android ...
- 用angular制作简单的选项卡
现在angular变得挺火热的,自己也去简单的学习了一下,学了几天下来觉得angular果然好用,但是现在只是停留在比较浅的层面上,要想学好angular还是得下一番功夫的.学了一点新知识就想和大家分 ...
- 使用kbmMWConfiguration 让 kbmmw smartservice 更聪明
以前的文章介绍了 很多 kbmmw smartservice 的使用,尤其是 rest 服务,所有的的配置都是通过 开发时写编码实现的,这样就可能导致,针对不同的应用环境,我们要重新编译代码,当然也可 ...
- version control
what 版本控制最主要的功能就是追踪文件的变更.它将什么时候.什么人更改了文件的什么内容等信息忠实地了已录下来.每一次文件的改变,文件的版本号都将增加.除了记录版本变更外,版本控制的另一个重要功能是 ...
- Concept Drift(概念漂移)
Introdution concept drift在机器学习.时间序列以及模式识别领域的一种现象.如果是在机器学习领域中,这个概念指的就是一个模型要去预测的一个目标变量,概念漂移就是这个目标变量随着时 ...