理解作用链的作用
1.函数在执行的过程中,先从自己内部找变量
2.如果找不到,再从创建当前函数所在的作用域去找, 以此往上
3.注意找的是变量的当前的状态
范例
var a = 1
function fn1(){
function fn2(){
console.log(a)
}
function fn3(){
var a = 4
fn2()
}
var a = 2
return fn3
}
var fn = fn1()
fn() //2
最后执行fn2函数,fn2找不到变量a,接着往上在找到创建当前fn2所在的作用域fn1中找到a=2;
var a = 1
function fn1(){
function fn3(){
var a = 4
fn2()
}
var a = 2
return fn3
}
function fn2(){
console.log(a)
}
var fn = fn1()
fn() //1
同上
var a = 1
function fn1(){
function fn3(){
function fn2(){
console.log(a)
}
fn2()
var a = 4
}
var a = 2
return fn3
}
var fn = fn1()
fn() //undefined
函数fn2在执行的过程中,先从自己内部找变量找不到,再从创建当前函数所在的作用域fn去找,注意此时变量声明前置,a已声明但未初始化为undefined;
理解作用链的原理:
前提:了解全局作用域,函数作用域,变量和函数的声明前置等基础;
函数的生命周期
函数的的生命周期分为创建和执行两个阶段。
- 在函数创建阶段,JS解析引擎进行预解析,会将函数声明提前,同时将该函数放到全局作用域中或当前函数的上一级函数的局部作用域中。
- 在函数执行阶段,JS引擎会将当前函数的局部变量和内部函数进行声明提前,然后再执行业务代码,当函数执行完退出时,释放该函数的执行上下文,并注销该函数的局部变量。
变量对象(Variable Object)
-
VO对应的是函数创建阶段,JS解析引擎进行预解析时,所有的变量和函数的声明,统称为Variable Object。
-
该变量与执行上下文相关,知道自己的数据存储在哪里,并且知道如何访问。
VO是一个与执行上下文相关的特殊对象,它存储着在上下文中声明的以下内容:
- 变量 (var, 变量声明);
- 函数声明 (FunctionDeclaration, 缩写为FD);
- 函数的形参
function add(a,b){
var sum = a + b;
function say(){
alert(sum);
}
return sum;
}
// sum,say,a,b 组合的对象就是VO
AO(活动对象)
- 对应的是函数执行阶段,当函数被调用执行时,会建立一个执行上下文,该执行上下文包含了函数所需的所有变量,该变量共同组成了一个新的对象就是Activetion Object。
该对象包含了:
- 函数的所有局部变量
- 函数的所有命名参数
- 函数的参数集合
- 函数的this指向
unction add(a,b){
var sum = a + b;
function say(){
alert(sum);
}
return sum;
}
add(4,5);
// 我用JS对象来表示AO
// AO = {
// this : window,
// arguments : [4,5],
// a : 4,
// b : 5,
// say : ,
// sum : undefined
// }
作用域链
-
1.当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain)来保证对执行环境有权访问的变量和函数的有序访问。
-
2.作用域第一个对象始终是当前执行代码所在环境的变量对象(VO),即在当前执行函数的作用域中寻找变量。
-
3.在函数运行过程中标识符的解析是沿着作用域链一级一级搜索的过程,从第一个对象开始,逐级向后回溯,直到找到同名标识符为止,找到后不再继续遍历,找不到就报错。
举例:
6.png
1 预处理后,进入全局上下文
7.png2 执行bar()函数
8.png3 查找变量
9.png4 执行foo()函数
10.png作者:彭荣辉
链接:https://www.jianshu.com/u/0f804364a8a8
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
网友评论