JS闭包解析
三点注意事项
- JS没有块级作用域,只有全局作用域和局部作用域(函数作用域)。
- JS中的作用域链,内部的作用域可以访问到外部作用域中的变量和方法,而外部作用域不能访问内部作用域的变量和方法。
- 当前作用域没有此变量或方法,会向外部作用域寻找变量或方法。
闭包的两种使用场景
函数作为返回值
function f() {
var a = 100;
return function () {
console.log(a);
}
}
var fn = f();
var a = 200;
fn(); // 输出100
调用fn函数,输出a的值,fn中并没有定义a,所以会向上找a,在f函数的作用域中,有a,值为100。所以就会输出100,并不会输出200。全局作用域中的a和f函数作用域中的a并不相同。这也体现出了闭包的一个好处:不会造成全局变量污染。
函数作为参数
function f() {
var a = 100;
return function () {
console.log(a);
}
}
var fn = f();
function f2(fn) {
var a = 200;
fn();
}
f2(fn);// 输出100
调用f2函数,传入fn函数,调用fn函数,输出a为100。
关于for循环和闭包之间的关系
var arr = [];
var i;
for (i = 0; i < 3; i++) {
arr[i] = function () {
return i;
}
}
console.log(arr[0]()); // 输出2
arr[0]()的结果,按照一般的思路来讲,应该是0才对,为什么是2呢?
- for循环3次,i的值从0变为2,arr这个数组中也添加了3个函数。
- 当调用
arr[0]函数时,for循环已经结束了,这时候i的值已经为2了,所以arr[0]函数取到的值为2。
如何解决这个问题?
var arr = [];
var i;
for (i = 0; i < 3; i++) {
arr[i] = (function (i) {
return function () {
return i;
}
})(i);
}
console.log(arr[0]()); // 输出0
这里,使用自执行匿名函数构造成一个独立作用域。每一次for循环的时候,都会执行这个匿名函数,并生成 一个匿名函数作用域。
比如第一次循环的时候,i = 0,将i作为参数传入匿名函数中,这样i的值就被保存在匿名函数作用域中。当调用arr[0]函数时,arr[0]就会取到匿名函数中的i的值。
闭包的实际应用
// 闭包实际应用中主要是封装变量,收敛权限
function isFirstLoad() {
var _list = [];
return function (id) {
if (_list.indexOf(id) > 0) {
return false;
} else {
_list.push(id);
return true;
}
}
}
var firstLoad = isFirstLoad();
firstLoad(1); // 返回true
firstLoad(1); // 返回false
firstLoad(2); // 返回true
闭包的缺点
目前主流浏览器采用的垃圾收集策略均为标记清除。当变量进入环境(比如,定义一个变量)时,就将这个变量标记为‘进入环境’,当变量离开环境时,就会被标记为‘离开环境’,就会被销毁。在刚才的闭包实际应用中_list变量一直被isFirstLoad的返回函数引用着,不会随着isFirstLoad的调用结束而销毁。所以_list变量会一直存在内存中。因此不能滥用闭包,否则就会造成网页性能问题,甚至内存泄漏。当我们不需要这些变量的时候,我们可以把这些变量的值赋值为null。
JS闭包解析的更多相关文章
- JS的解析与执行过程
JS的解析与执行过程 全局中的解析和执行过程 预处理:创建一个词法环境(LexicalEnvironment,在后面简写为LE),扫描JS中的用声明的方式声明的函数,用var定义的变量并将它们加到预处 ...
- js闭包的作用域以及闭包案列的介绍:
转载▼ 标签: it js闭包的作用域以及闭包案列的介绍: 首先我们根据前面的介绍来分析js闭包有什么作用,他会给我们编程带来什么好处? 闭包是为了更方便我们在处理js函数的时候会遇到以下的几 ...
- 大部分人都会做错的经典JS闭包面试题
由工作中演变而来的面试题 这是一个我工作当中的遇到的一个问题,似乎很有趣,就当做了一道题去面试,发现几乎没人能全部答对并说出原因,遂拿出来聊一聊吧. 先看题目代码: function fun(n,o) ...
- Js闭包常见三种用法
Js闭包特性源于内部函数可以将外部函数的活动对象保存在自己的作用域链上,所以使内部函数的可以将外部函数的活动对象占为己有,可以在外部函数销毁时依然存有外部函数内的活动对象内容,这样做的好处是可 ...
- js闭包之初步理解( JavaScript closure)
闭包一直是js中一个比较难于理解的东西,而平时用途又非常多,因此不得不对闭包进行必要的理解,现在来说说我对js闭包的理解. 要理解闭包,肯定是要先了解js的一个重要特性, 回想一下,那就是函数作用域, ...
- JS的解析机制
JS的解析机制,是JS的又一大重点知识点,在面试题中更经常出现,今天就来唠唠他们的原理.首先呢,我们在我们伟大的浏览器中,有个叫做JS解析器的东西,它专门用来读取JS,执行JS.一般情况是存在作用域就 ...
- (原创)JS闭包看代码理解
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...
- js闭包理解
js闭包的作用是使函数外可以访问函数内部的变量,是通过 在函数内部 定义 访问函数内变量 的函数实现的,内部的一个函数产生一个闭包 function a() { var i=0; return fun ...
- js的解析--预处理(三)
js的解析与执行过程 分全局 {预处理阶段和执行阶段} 函数{预处理函数和执行阶段} 1/创建词法环境(环境上下文) LexicalEnvironment === window { } ...
随机推荐
- APP测试点注意事项汇总
1.异常测试:包括业务流程的异常情况:业务场景的异常:操作习惯的异常(比如答题过程中会出现声音干扰这样很不友好喔~) 2.网络测试:网络切换的过程中,APP会不会异常:断网情况进行一些操作,APP会不 ...
- Django组件-cookie与session
一.会话跟踪技术 1.什么是会话跟踪技术 我们需要先了解一下什么是会话!可以把会话理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应.例如你给10086打个电话,你就是客户端,而 ...
- el-table中单数行与双数行设置不同的背景颜色
<el-table :cell-style='cellStyle' :data="tableData" style="width: 100%;" > ...
- powermock单元测试小结
最近时不时的需要单元测试来写覆盖率.简单总结一下日常心得: 1.首先指明需要测试的类:@PrepareForTest({ RewardGoldServiceImpl.class }) 2.其次在测试类 ...
- SQL优化(面试题)
因为现在面试经常需要问的需要SQL优化,问的具体操作步骤时候的常见做法,所以网上总结这些操作步骤: SQL优化的具体操作: 1.在表中建立索引,优先考虑where.group by使用到的字段. 2. ...
- python+selenium自动测试之WebDriver的常用API(基础篇二)
本篇介绍一下python+selenium复杂操作的处理,基于python3.6,selenium3.141,详细资料介绍查看官方API文档,点击这里 一.常见特殊情况处理如iframe/弹窗处理 有 ...
- windows下安装Python虚拟环境virtualenvwrapper-win
1 前言 由于Python的版本众多,还有Python2和Python3的争论,因此有些软件包或第三方库就容易出现版本不兼容的问题. 通过 virtualenv 这个工具,就可以构建一系列 虚拟的 ...
- Rafy 框架 - 时间戳插件
本文将解释 Rafy 框架中的时间戳插件的场景.使用方法.原理. 场景 在开发各类数据库应用系统时,业务领域实体往往需要包含"创建时间"."最后更新时间".&q ...
- 2018—2019-- 2网络对抗技术20165239Exp信息搜集 漏洞扫描
一.实验内容 二.实验步骤 1.各种搜索技巧的应用 2.DNS IP注册信息的查询 3.基本的扫描技术 主机发现 端口扫描 OS及服务版本探测 具体服务的查点 4.漏洞扫描 三.实验中遇到的问题 四. ...
- selenium使用遇到的问题(selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PATH.)
1.安装pip3 install selenium 2.使用browser=webdriver.Chrome()时报错 :selenium.common.exceptions.WebDriverExc ...