作用域、作用域链以及闭包

在js中,作用域分为全局作用域、函数作用域、块级作用域。

作用域

作用域就是一个变量在代码运行时可被访问的范围。作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。

全局作用域
<script>
	var a = 1
<script/>

像这种直接定义在window上的变量就具有全局作用域,全局作用域里的变量可以被全局访问,但是这也就造成了一个问题,当定义了全局变量之后,没有销毁的话,容易造成内存泄露。

函数作用域
<script>
	var a = 1
	function fn(){
		let i = 2
		console.log(a) // 1
	}
<script/>

由function所定义出的函数,其里面的变量具有函数定义域的作用范围,里面的变量只能在该函数中可以被访问,例如window中就无法访问i,这里的i就具有块级作用域,其由let、const定义的变量会具有块级作用域,块级作用域的范围是let所在的大括号{}的范围。

作用域链

作用域链就是由全局作用域与函数作用域所组成的变量查找顺序。需要注意的是,作用域链在js预编译阶段就已经确定。

<script>
	var a = 1
	function fn(){
		let i = 2
		console.log(a) // 1
	}
<script/>

函数作用域内可以访问到全局作用域的变量a这就是作用域链的原因,接下来我会好好分析一下这个过程
在这里插入图片描述
预编译阶段:
1、全局预编译产生GO
2、函数预编译产生AO
3、在自己的作用域将所有变量进行定义并赋值。
所谓作用域链其实就是在‘里面’的作用域可以访问外层作用域的变量(前提是自己没有)。这个‘里面’的意思其实就是包裹的意思,但是需要注意的一点是每个函数作用域是独立的,互为兄弟的函数,不能访问相互的变量,除非在他们内部有变量被定义到了他们的父作用域或者window上(b = 5这种)。

这只是个小例子,但也是作用域链原理最简单的表述,下面给个例子验证一下自己是否懂得了原理。

var a = 1
function f1() {
     console.log(a);
}
function f2() {
    var a = 2
    f1()
}
 f2() // 1

根据上面的分析,可以知道f1其实是在window下的函数作用域,尽管在f2中运行,但是其作用域在预编译阶段就已经被确定了。(如果没懂的话,可以跟我上面一样,画个图加深印象和理解)

闭包

了解了作用域链相关知识,不知道大家有没有联系到js中一个非常重要的知识点—闭包。闭包的定义是,函数内部可以引用函数外部的变量。其实,你看看上面那个例子,就可以明白闭包的底层原理其实就是作用域链。
以上例为例,在f1函数内部中没有变量a,去函数外部找,比较特殊的是外面是全局作用域,但是这个完全是符合闭包定义的。

先给一个典型的闭包例子

function f1(){
	var a = 1
	function f2(){
		console.log(a++)
	}
	return f2
}
const fn = f1()
fn()
fn()
fn()

利用作用域链分析:
在这里插入图片描述
显然f2可以访问a变量,且会被存储在fn中不会删除,这就是闭包。
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值