作用域
一、函数执行
1.1 全局代码执行顺序
编译:在执行调用栈(ECStack)中创建一个全局对象(globalobject),将代码中的变量添加到全局对象中,此时变量值均为undefined。
运行:在全局执行上下文(GEC)中有可变对象(VO),指向堆中的全局变量(GO)。在运行过程中通过GO完成对编译过程中变量的赋值。
1.2 函数执行上下文(FEC)
编译:函数编译过程中会包含父级作用域(parents cope)。父级作用域为函数上一层,父级作用域由编译时确定,与调用时无关)
运行:在函数执行上下文(FEC)中有可变对象(VO),指向堆中的函数变量(AO)。在运行过程中通AO完成对编译过程中变量的赋值。
二、作用域链
2.1 作用域链(Scope Chain)
产生:在编译过程中会形成一个作用域链,在查找变量中实际是通过作用域链查找。
组成:VO+ParentScope
2.2 面试题
var n = 100
fuction foo() {
n = 200 //此时的n并没有新建变量,n为全局变量中定义的 var n
}
foo()
console.log(n) //200
fuction foo() {
console.log(n) //undefined 此时只完成变量n定义,并未赋值
var n = 200
console.log(n) // 200 此时变量n已完成赋值
}
var n = 100
foo()
var n = 100
function foo1() {
console.log(n) //100 在父级作用域(gl)中找,看编译不看引用
}
function foo2() {
var n =200
console.log(n) //200
foo1()
}
foo2()
console.log(n) //100 在全局作用域找
var a = 100
function foo() {
console.log(a) //undefined
return //return返回后不继续往下执行 但在编译中还会编译变量a
var a = 100
}
foo()
function foo() {
var a = b = 100 //var a = 100 b=100
}
foo()
console.log(a) //访问不到 a定义在AO中,在全局对象中查找不到
console.log(b) //100 b可看为在全局对象中定义