最近在看控制台的时候,突然发现一个神奇的内部属性[[Scopes]]
这勾起了我对作用域的深深回忆:
- 每个
函数都有自己的作用域,作用域中包含了该函数声明的所有顶层变量 函数可以访问上层的作用域,也就是说,当查找变量时,如果执行的函数本身没有这个变量,那就会向上查找,直到全局作用域,这样就形成了作用域链作用域是静态词法作用域,也就是说在函数声明时就已经确定了
实际上,在早前,查看作用域只能在调试时查看,例如:
let c = 1;
function a() {
let d = 1
return ()=> {
let e = 1;
console.log(c)
console.log(d)
debugger
}
}
可以看到这里有四个属性:
先简单的介绍一下这几个属性:
- Local:就是
当前执行函数的顶层变量,注意是顶层变量,这里就是e,块级作用域的变量实际上是用另一个表示----Block - Closure:归类为
闭包的变量,也就是a函数中的b - Script:
全局脚本变量,这里可以看到我们声明的c - Global:
全局window对象
当然这一定要在调试的时候查看。但是,现在有了更加快捷的方式,就是用[[Scopes]],重新组织刚才的代码:
let c = 1;
function a() {
let d = 1
return function f() {
let e = 1;
console.log(c)
console.log(d)
console.dir(f) // 输出f函数
}
}
可以看到几乎输出了一样的输出,只是没有Local,当然为什么没有Local,主要是函数没运行,所以只能确定静态词法作用域,所以这里又对应上了静态词法作用域。
当然既然看到了Closure,这就不得不提到作用域的一种特殊形式闭包,先来简单回忆一下闭包(Closure):
1.闭包(Closure)就是函数携带其它函数作用域的一种形式
这里有一点要注意,闭包是函数和函数之间存在的,来一个例子佐证:
function a() {
{
let d = 2;
function b() {
console.log(d);
console.dir(b);
debugger ;
}
b()
}
}
可以看到函数b引用了上层块级作用域的变量,但是没有闭包(Closure)
所以[[Scopes]]这个内部属性,还是非常有用的,不过目前的御三家,火狐是没有的: