# 预解析与作用域
# 环境
运行环境 是JavaScript中重要的一个概念,指JavaScript代码运行的地方
- 宿主环境: 指支持JavaScript运行的平台或软件,一般指浏览器
- 执行环境: 定义了变量或函数有权访问的其他数据,决定了它们各自的行为
- 全局环境:整个页面
- 函数环境:一个函数内部就是一个环境
- eval()
正因为有了这些环境,在不同环境中声明的变量或函数就有了它的生效范围,这就是作用域:
# 作用域
作用域:作用域即一段代码的作用范围。
# 全局变量
在全局环境(即函数外部)声明的变量,或者没有使用var关键字声明的变量,在任何地方都可以访问得到,拥有全局的作用域。
# 局部变量
在函数环境(即函数内部)声明的变量,参数也是局部变量。只能在函数内部访问得到。
var a=100;
function aa(){
alert(a);
var b = 200;
alert(b);
c = 1;
}
aa(); // 100 200
alert(a); //100
alert(b); //报错
alert(c);
优点:可以提高程序的逻辑性、安全性,可以减少名字的冲突。
# 作用域链
当访问一个变量或函数时,JavaScript会创建变量的一个作用域链,规定了该变量在执行环境中的访问次序:从当前环境开始,依次到包含(外部)环境、下一个包含环境,直到全局环境。
直观表现就是:变量函数的值会从当前作用域寻找,然后逐级地向上级回溯,直至找到变量为止(如果找不到变量,通常会导致错误发生)。
var num = 1;
function aa(){
var num = 2;
function bb(){
var num = 3;
function cc(){
num = 4;
alert(num); // 4
}
cc();
alert(num); // 4
}
bb();
alert(num); // 2
}
aa();
alert(num); // 1
注意:
不用var声明直接为变量赋值,得到的不是真正的全局变量,它实际是对属性赋值操作。首先,它会尝试在当前作用域链中解析 改变量; 如果在任何当前作用域链中找到改变量,则会执行对改变量属性赋值; 如果没有找到改变量,它才会在全局对象(即当前作用域链的最顶层对象,如window对象)中创造改变量属性并赋值。
# 预解析
JavaScript解析器在运行JavaScript代码的时候会将
变量
、函数
提前到当前作用域顶部,再顺序执行。
预解析顺序:
- 按
<script> </script>
块依次来解析的 - 按执行环境来解析
- 全局环境:打开页面解析
- 函数环境:调用该函数的时候解析
- 遇到关键字var和function时,提前解析到内存中
- 如果还有
<script> </script>
块,再按上述顺序来解析
案例:
- 全局环境预解析
- 函数环境预解析
- 分块解析
预解析案例:
alert(a); // undefined
var a = 12;
alert(a); // 12
alert(b); // b is not defined
var num = 10;
function fun() {
var num
console.log(num) // undefined
num = 100
}
fun()
console.log(fun); // 函数fun
var fun = 123;
function fun() {
console.log('Hello javascript');
}
console.log(fun); // 123