面试官:聊聊作用域问题
全局作用域
script
标签所在的区域就是所谓的全局作用域,全局作用域有一个全局的对象 window
我们所有定义的变量,函数,类,对象等等都是作用域 window
对象身上的
var a = 1
// 就是在window 对象上加上一个 a 属性
局部作用域(特指函数作用域)
function foo(a) {
console.log(a)
}
foo(2)
会产生一个局部作用域,暂且叫做 fooScope, 这个作用域里面存储着这个局部作用域里面的所有变量定义,函数定义,对象定义等等。值得注意的是,全局作用域 globalScope 总是被我们忽视了,局部作用域是可以访问全局作用域的。
所以
globalScope(顶层)
|
|
fooScope(当前)
发出疑问
既然局部作用域能够访问全局作用域的变量,那么局部作用域能不能修改全局作用域变量的值呢?
答案是可以的,我们来看个简单的例子
var a = 1
function foo() {
a = a + 1
console.log(a); // 2
}
foo()
console.log(a) // 2
函数参数是值引用
var a = 1
function foo(a) {
a = a + 1
console.log(a)
}
foo(a) // 2
console.log(a) // 1 说明全局中的 a 与函数参数的 a 存储的地方不一样
嵌套作用域
var a = 1
function foo(a) {
function bar(a) {
console.log("bar ===>", a)
console.log(this)
}
console.log("foo", this)
bar(a)
}
foo(a)
打印出来的顺序如下:
foo: window
bar===> 1
window
先来说说这个 a 的寻找过程:
bar 执行,会在自己的作用域 barScope 找这个变量 a 发现找不到,会在 fooScope 作用域找,发现找不到 就找到全局作用域 window 中,发现有 a 这个变量
我们来验证下寻找的过程:
var a = 1
function foo() {
var a = 2
function bar() {
console.log("bar ===>", a)
console.log(this)
}
console.log("foo", this)
bar()
}
foo()
打印出来如下:
foo:window
bar===>2
bar:window
所以找到要用到的变量之后,就会停止寻找了。
执行顺序
词法解析
解析全局作用域,函数,变量
语法解析
生成程序结构树
代码生成
执行代码
var a = 1
function foo() {
var a = 2
function bar(a) {
console.log("bar ===>", a)
console.log("bar ===>",this)
}
console.log("foo", this)
bar(a)
}
foo()
所以
解析阶段
全局作用域 有变量 a foo 作用域 有 fooScope.a/window.a bar 作用域 有barScope/fooScope.a/window.a
执行阶段
bar 执行返回,销毁 foo 执行返回,销毁 window
这样就形成了作用域链
评论