let a = 1 // globalScope 的变量 a
let f0 = () => console.log(a)
let f1 = (a) => { // f1Scope 中存在变量 a
f0()
console.log(a)
}
f1(2) //=> 1, 2
由于 f0 被定义时所处的环境 globalScope 存在变量 a , 而 f0 函数里面 f0Scope 并没有变量 a, 故执行 f0() 时, 其中的 console.log(a) 语句会找到 globalScope 的变量 a, 并输出
而 f1 则是在函数内部 f1Scope 就存在变量 a, 因此不会向上查找到其所处的环境 globalScope 的变量 a, 因此执行 f1 时, 其中的 console.log(a) 语句会找到 f1Scope 的变量 a 输出
之所以可以从一个作用域向上查找到另一个作用域, 就是因为作用域链的存在
2. 作用域链
规则: 当在一个函数内部查找不到想要的变量时, 浏览器会沿着其作用域链向上级作用域继续查找, 如果找到了就返回对应的值, 如果直到 global 作用域都找不到, 则返回 undefined
在 Chrome 浏览器中通过 console.dir 打印出来可以看到作用域链是怎样的
var a = 1
let b = 2
const c = 3
let f0 = () => {
console.dir(f0)
let f1 = () => {
console.dir(f1)
let f2 = () => {
console.dir(f2)
}
f2()
}
f1()
}
let f = () => {
console.dir(f)
f0()
}
f()
1. 作用域
对于 JavaScript 来说, 其作用域被称作词法作用域, 通俗一点的说法就是静态作用域:
规则: 一个函数的作用域与其被调用的位置无关, 而是与其被定义时所处的环境有关
结合代码理解:
之所以可以从一个作用域向上查找到另一个作用域, 就是因为作用域链的存在
2. 作用域链
规则: 当在一个函数内部查找不到想要的变量时, 浏览器会沿着其作用域链向上级作用域继续查找, 如果找到了就返回对应的值, 如果直到 global 作用域都找不到, 则返回 undefined
在 Chrome 浏览器中通过 console.dir 打印出来可以看到作用域链是怎样的
下图所示的 [[scopes]] 对应的就是相应函数所拥有的作用域链(Script 对应的是在全局上使用 let/const 定义的变量(因为 let 和 const 定义的变量并不会添加到 window 对象中))