JavaScript 是基于词法作用域的语言:通过阅读包含变量的源代码就可以知道变量的作用域。全局变量在程序中始终都是有定义的,而局部变量在它所声明的函数体以及它所嵌套的函数内始终都是有定义的。
每一段函数定义,以及全局代码,拥有一个与之关联的作用域链。这个作用域链可以看作一个对象链表,链表中的对象定义了所关联代码的作用域中的变量。当 JavaScript 需要查找变量 x 的时候,它需要从作用域连表中的第一个对象开始查找,如果对象中没有属性 x,那么继续查找下一个对象,以此类推,最后一个对象为全局代码的作用域,如果依然查找不到,将抛出一个 ReferenceError 异常。
下面是三个 🌰:
- 在这段全局代码中,作用域链中仅有一个代表顶级作用域的对象,它有一个属性 foo,表示全局变量 foo
var foo = "hello world"
- 在全局代码中声明的函数 func1 的作用域链有两个对象,第一个对象拥有两个属性:函数的阐述 bar,和局部变量 bar2。在函数 func1 中访问变量 foo , 将访问作用域链的第二个对象中的属性 foo。
var foo = “hello world”
function func1(bar) {
var bar2 = "blur blur"
console.log(bar, bar2, foo)
}
- 嵌套函数 func2 点作用域链有三个对象,第一个对象是 func2 函数本身的作用域,第二个对象是 func 函数的作用域,第三个对象是全局作用域。即使将 func2 当作返回值,返回到 func 函数的外部,也不会改变 func2 本身的作用域链。
var foo = “hello world”
function func1(bar) {
var bar2 = "blur blur"
function func2() {
var bar3 = "blur blur"
console.log(bar, bar3, foo)
}
return func2
}
网友评论