文档章节

JS闭包

x
 xszl
发布于 2017/08/26 19:43
字数 947
阅读 15
收藏 0

javascript中最为重要的两个概念:原型链、闭包。原型链在上次的文章中有分析过,这次说下闭包。 ##执行环境和作用域链 要理解闭包,我们先得了解javascript的执行环境和作用域链的概念。

执行环境定义了变量或者函数有权访问的其他数据,每个执行环境都有一个与之关联的变量对象(作用域),环境中定义的变量都存储在这个对象中。

进入一个函数时,它的执行环境会被压入到一个环境栈中,然后根据它的变量对象创建一个作用域链,顺序就是环境栈中的顺序,全局执行环境的变量对象是作用域链中的最后一个,该函数的执行环境的变量对象是最前端。等到函数执行完,销毁作用域链并将执行环境弹出环境栈。

函数中对于变量的查找就是顺着这个作用域链一级一级搜索。所以在函数内部可以读取全局变量,而在函数外部是无法读取函数内部变量 ##从外部访问函数内部变量 基于作用域链的原理,函数的变量只有自己和它的子函数能访问,如果我们将这个子函数返回给外部的一个变量,会发生什么?

	function f1() {
		var num = 1;
		return function f2() {
			console.log(num);
		}
	}
	var func = f1();
	func();

我们在控制太会看到有输出,为什么呢?f1在执行完返回f2的时候,f1的执行环境会弹出环境栈,它的作用域链也会被摧毁,但是因为返回的f2函数的作用域链有在引用f1的活动对象,所以f1的活动对象并不会摧毁,只要f2不被销毁,f2会带着f1的作用域,所以在全局环境中调用func(),也就是调用f2,能访问f1的变量num。 ##闭包的概念 上述中的子函数f2就是闭包。闭包就是定义在一个函数内部的一个函数,它将函数的内部和外部连接了起来,让在函数外部能够有权访问函数内部的变量

其实这个父函数f1很像是一个类,里面定义的变量就是它的私有属性,外部需要访问f1里的私有属性,怎么办?提供一个共有方法f2给外部调用。f2就是闭包 ##闭包的作用 使用闭包有两个好处

  • 能从函数外部访问函数内部变量
  • 保存状态
	function f1() {
		var num = 1;
		return function f2() {
			console.log(num);
			num++;
		}
	}
	var func = f1();
	func();
	func();

控制台会输出1、2。这是因为第一次调用func之后,闭包会携带包含环境f1的作用域,所以会保存num的状态(已加1),第二次调用那么就会显示2.。

##闭包的问题 闭包的这种机制会带来一些问题

  • 闭包由于会携带包含环境的作用域,因此会占用更多的内存
  • 闭包只能取得包含环境中变量的最后一个值
	function f1() {
		var result = new Array();

		for(var i = 0; i < 10; i++) {
			result[i] = function() {
				return i;
			}
		}
		return result;
	}
	for (var i = 0; i < 10; i++) {
		console.log(f1()[i]());
	}

由于闭包保存的状态i最后是10,所以上述示例会返回10个10,而不是0-9。我们需要再在外面套一层闭包来解决。

	function f1() {
		var result = new Array();

		for(var i = 0; i < 10; i++) {
			result[i] = function(num) {
				return function() {
					return num;
				}
			}(i)
		}
		return result;
	}
	for (var i = 0; i < 10; i++) {
		console.log(f1()[i]());
	}

由于闭包存在的这些问题,所以一定要谨慎使用。

© 著作权归作者所有

x
粉丝 0
博文 14
码字总数 17267
作品 0
私信 提问

暂无文章

浅析大数据 学习大数据后能做什么

大数据时代的到来使得大数据开发人才迎来了前所未有的机遇和挑战!一个绝佳的入行机会摆在了众人面前!于是,很多人都在打听,大数据到底有何应用?可以用来做什么?好程序员今天就为大家作出...

好程序员IT
24分钟前
1
0
C# USB视频人脸检测

此程序基于 虹软人脸识别进行的开发 SDK下载地址:https://ai.arcsoft.com.cn/ucenter/user/reg?utm_source=csdn1&utm_medium=referral 前提条件 从虹软官网下载获取ArcFace引擎应用开发包,...

是哇兴哥棒棒哒
35分钟前
2
0
Vagrant虚拟机硬盘扩容

# 停止虚拟机vagrant halt <machine_name># 进入VirtualBox VMs目录,查看并记录原磁盘uuid,留作后用vboxmanage showhdinfo box-disk1.vmdk# 克隆磁盘,vmdk格式无法调整大小,需要...

sskill
37分钟前
1
0
分布式商业萌芽,银行迎来发展新机遇

01 分布式商业萌芽,银行迎来发展新机遇 金融界:近几年区块链的热度经历了过山车般的转折。目前追逐区块链的资本也开始冷静下来,于此同时,各大商业银行对区块链的研究应用也越来越多。您认...

Java领航员
42分钟前
3
0
Spring系列教程六: Spring jdbcTemplate在Dao中的使用

概念 Spring中的jdbcTemplate的主要作用是实现数据的交互,下面我们就在dao层中如何使用jdbctemplate写测试案例 项目目录如下 基于xml实现jdbctemplate 这里我们使用的是JdbcDaoSupport这个类...

我叫小糖主
46分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部