定义
用来查找变量的值的规则集 决定一个变量的范围
块作用域
js 没有 java有
函数作用域
js 类似
动态作用域(只有当运行的时候才确定变量的作用域)
js也没有
词法作用域(也称为静态作用域或闭包)
1、js的作用域解析
在函数创建时(解析器读取代码时),就给函数添加了一个[[scope]]成员,[[scope]]指向该函数创建的环境,
当函数真正执行时,会创建自己的词法环境[[le]],并使自己的[[le]]关联[[scope]],那么该 函数可以获得的成员属性, 就为自己的[[le]]和[[scope]],
就算该函数脱离了创建环境,也可以拿到之前的成员属性。
当函数真正执行时,会创建自己的词法环境[[le]],并使自己的[[le]]关联[[scope]],那么该 函数可以获得的成员属性, 就为自己的[[le]]和[[scope]],
就算该函数脱离了创建环境,也可以拿到之前的成员属性。
2、用new Function创建函数
创建的作用域指向window
3、作用域链
函数预处理阶段函数的[[scope]]指向父函数的词法环境函数执行阶段函数内部的词法环境指向函数的[[scope]]
g.le -> g.[[scope]]== f.le -> f.[[scope]] == window
那么问题来了什么是 静态作用域?
静态作用域就是函数声明时,就已经订好的作用域,以后也不会改变的作用域就是静态作用域。
举例说明
<script type="text/javascript">
alert(fn);//function fn(){function fn1(){function fn2(){}}}
function fn(){
var a = 0;
function fn1(){
var b = 1;
function fn2(){
return b;
}
}
}
</script>
alert 在预处理阶段打印出全部函数体结构。 事实证明在函数声明时就已经确定好作用域。
再来看一个例子
<script type="text/javascript">
window.a=5;
function out(){
//[[scope]] == window
var a=1;
alert(a);//1
function inner(){
//inner.[[scope]] == out.[[le]]
var a=2;
alert(a);//2
}
inner();
}
out();
</script>
out的创建环境是window inner的创建环境是呕吐的词法作用域。
在inner 寻找某个变量是 首先会去找自己的词法作用域 再去找 自己的创建环境作用域 再去找 out的创建环境作用域。
也可以理解为 冒泡寻找,从里置外的寻找。
inner.[[le]]-->inner.[[scope]]==out.[[le]]-->out.[[scope]]==window
再来看一个例子
<script type="text/javascript">
window.a=5;
function out(){
var a=1;
return function inner(){
alert(a);//1
}
}
var inn= out();
inn();
</script>
在inner()函数脱离了自己的创建环境后,还能用到创建前作用域的成员属性。
还是回到了之前那句话什么是静态作用域 :
静态作用域就是函数声明时,就已经订好的作用域,以后也不会改变的作用域就是静态作用域。