浅谈JS执行上下文,作用域以及闭包

执行上下文

首先要知道js执行到可执行语句时,就会创建一个上下文,等到这个上下文执行上下文执行完毕,就会出栈,继续执行下面的代码,也有可能进入其他的上下文。
那么创建上下文有什么用呢?
用于确认变量是否可访问,确定this指向,以及变量的赋值。
创建上下文有两个阶段:

创建阶段:

该创建属于变量声明阶段,创建变量对象AO

function func(a,b){
	console.log(c)
	console.log(d)
	var c=10
	function d(){
		
	}
}
func(1,2)
//伪代码
AO[func]={
	a:1,
	b:1,
	c:undefined,
	d:function
}

创建阶段其实就是变量声明的过程。

执行阶段:

执行代码阶段。这个阶端AO转换成VO,以及会新增arguments对象。this开始会指向一个明确的对象。
拿上面那个例子举例:其实很多小伙伴以前会觉得console.log(c)这一条语句为什么会答应出undefined这样的结果,而不是c is not defined? 然后网上一查,结果大多都是变量提升。
当你深入执行上下文之后 ,你就会知道,在执行console.log(c)之前有上下文创建阶段啊。AO中已经声明了a,只不过创建阶段不会赋值而已,所以就是undefined。
小伙伴又会问,为什么打印d的时候是函数体呢?
其实函数是js第一公民,声明函数是不用赋值语句的,在创建阶段就会把函数体指向d这个属性。

作用域链(scope)

在了解作用域之前,有必要先了解一下静态作用域这个概念,因为js是静态作用域的。
静态作用域:作用域是函数定义时就确定了的。
所以作用域链是在上下文创建阶段就确定了的。
一个函数的作用域链是自身活动变量加上级的活动变量们的集合。

闭包

可以访问到自由变量的函数就是闭包。
自由变量:不存在在自身上下文VO中的变量
其实根据定理可以看出js中所有的函数都可以是闭包,因为js中每个函数都有访问上级作用域的确定。

但一个函数能否访问另一个函数中的变量呢?问题变得复杂了起来。
本来函数执行完毕就会出栈,另一个函数根本不可能访问已出栈函数中的变量。
假设:已出栈函数为A,另一个函数为B。
我们能否把A的上下文环境的引用给B呢,这样就愉快解决问题了呢~

function clourse(){
	var h=10
	return function(){
		h++
		console.log(h)
	}
}
let a=clourse()
a() //11
a()	//12

clourse函数为A,A的返回值为B,当A执行完毕,返回值B赋值给了变量a。这样是不是变量a就拥有了A的上下文环境的VO。
于是函数a就能愉快的访问变量h了呢。

神奇的JS!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值