04------JS函数高级之作用域(链)、闭包

作用域和作用域链

1.作用域
理解:

  • 就是一块地盘,一个代码所在的区域
  • 它是静态的(相对于上下文对象),在编写代码的时候就已经确定

分类:

  • 全局作用域
  • 局部作用域
  • 块作用域(ES6)

作用:

  • 隔离变量,不同作用域下同名变量不会有冲突

在这里插入图片描述
2.作用域和执行上下文

1).区别1

  • 全局作用域之外,每个函数都会创建自己的作用域,作用域在函数定义时就已经确定,而不是在函数调用时
  • 全局执行上下文环境是在全局作用域确定之后,js代码马上执行之前创建
  • 函数执行上下文是在调用函数时,函数体代码执行之前创建

2).区别2

  • 作用域是静态的,只要函数定义好了就会一直存在,且不会再变化
  • 执行上下文环境是动态的,调用函数时创建,函数调用结束时上下文环境会被动态释放

3).联系

  • 执行上下文环境(对象)是从属于所在的作用域
  • 全局上下文环境---->全局作用域
  • 函数上下文环境---->对应的函数使用域
    在这里插入图片描述
    3.作用域链

1).理解

  • 多个上下级关系的作用域形成的链,它的方向是从下向上的(从内到外)
  • 查找变量时就是沿着作用域链来查找的

2).查找一个变量的规则

  • 在当前作用域下的执行上下文中查找对应的属性,如果有直接返回,否则进入2
  • 在上一级作用域的执行上下文查找对应的属性,如果有直接返回,否则进入3
  • 再次执行2的相同操作,直到全局作用域,如果还找不到就抛出找不到的异常

图解:
在这里插入图片描述
面试题:
1).

<script type="text/javascript">
var x = 10;
function fn() {
	console.log(x) // 10
}
function show(f) {
	var x = 20
	f()
}
show(fn)
</script>

2).

<script type="text/javascript">
var fn = function () {
	console.log(fn) //输出fn函数
}
fn()
var obj = {
	fn2: function () {
		console.log(fn2) //报错 fn2未定义
	}
}
obj.fn2()
</script>

闭包

1.闭包的理解

1).如何产生闭包?

  • 当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包

2).闭包到底是什么?

  • 理解一:闭包是嵌套的内部函数
  • 理解二:包含被引用变量(函数)的对象
  • 注意:闭包存在于嵌套的内部函数中

3).产生闭包的条件?

  • 函数嵌套
  • 内部函数引用了外部函数的数据(变量/函数)

2.常见的闭包

  • 将函数作为另一个函数的返回值
function fn1() {
	var a = 2
	function fn2() {
		a++
		console.log(a)
	}
	return fn2
}
var f = fn1()
f() // 3
f() // 4
  • 将函数作为实参传递给另一个函数调用
function showDelay(msg, time) {
	setTimeout(function () {
		alert(msg)
	}, time)
}
showDelay('hello', 1000)

3.闭包的作用

  • 延长了局部变量的生命周期
  • 在外部能够间接的操作内部的变量

4.闭包的生命周期

  • 产生:在嵌套内部函数定义执行完时就产生了(不是在调用)
  • 死亡:在嵌套的内部函数成为垃圾对象时
<script type="text/javascript">
	function fn1() {
		var a = 2
		function fn2() {
			a++
			console.log(a)
		}
		return fn2
	}
	// 问题1:此时闭包产生了吗? 已产生
	var f = fn1()
	// 问题2:此时闭包释放了吗? 没有
	f() 
	f() 
	// 问题3:此时闭包释放回收了吗? 没有
	// 问题4:如何让闭包释放回收呢? f = null
</script>

5.闭包的应用
自定义JS模块

  • 具有特定功能的js文件
  • 将所有的数据和功能都封装在一个函数内部(私有的)
  • 只向外部暴露一个包含n个方法的对象或函数
  • 模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能

6.闭包的缺点以及解决
缺点

  • 函数执行完后,函数内的局部变量没有释放,占用内存时间会变长
  • 容易造成内存泄露

解决

  • 能不用闭包就不用
  • 及时释放

内存溢出与内存泄露

1.内存溢出

  • 一种程序运行出现的错误
  • 当程序运行需要的内存超过了剩余的内存时,就会抛出内存溢出的错误

2.内存泄露

  • 占用的内存没有及时释放
  • 内存泄露积累多了就容易导致内存溢出
  • 常见的内存泄露:
    • 意外的全局变量
    • 没有及时清理的计时器或回调函数
    • 闭包
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值