作用域
全局作用域和局部作用域
全局作用域:整个script标签中的区域
局部作用域:函数内部的区域,代码只在函数内部起效果
全局变量和局部变量
全局变量:在全局都可以使用,在全局作用域下声明的变量或者在函数内部未声明直接使用(不推荐使用)的变量成称为全局变量
局部变量:只能在函数内部使用;在函数内部声明的变量叫局部变量;函数的形参实际上也是局部变量
注意:当前的js中是没有块级作用域的。块级作用域:被花括号’{}‘包含的区域
作用域链
根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链。
在作用域链的案例中,实际上也就是就近原则;
接下来我们看一个案例:
function f1() {
var num = 123;
function f2() {
console.log(num);
}
f2();
}
var num = 456;
f1()
该代码的输出结果为123;
我们可以看到输出的是离它最近的一个值;实际上这个过程就是一个向外部查询值的过程。
再看一个案例:
var a=1;
function fn1(){
var a=2;
var b='22';
fn2;
function fn2(){
var a=3;
fn3();
function fn3(){
var a=4;
console.log(a);
console.log(b);
}
}
}
fn1;
这个代码a的结果为4,b的结果为’22’;
我们可以看到,相当于是从输出的时候依次往外找,照道离他最近的那个值。
但在这里,我们要注意一件事,函数只有在调用的时候才会执行,所以做这种题时记得避免踩坑。
预解析
js引擎运行js时分为两步:预解析 代码执行
预解析:js引擎会把js里面所有的var和function提升到当前作用域的最前面
代码执行:按照代码书写的格式从上往下执行
变量预解析
将所有变量声明提升到当前作用域的最前面,不提升赋值操作
函数预解析
将所有函数声明提升到当前作用域的最前面,不调用函数
案例
预解析是在面试时经常会遇到的考点,这里我们给出几个案例练习一下。
案例一
var num=10;
fun();
function fun(){
console.log(num);
var num=20;
}
输出结果
undefined
这里我们可以看到,函数内部会将var num提升到函数的最上面,但此时并没有赋值,所以会输出undefined。
案例二(一道经典的面试题)
f1()
console.log(c);
console.log(b);
console.log(a);
function f1() {
var a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}
输出结果
9
9
9
9
9
出错
这里的var a=b=c=9就相当于是var a=9;b=9;c=9;前面我们提到了在函数中未声明的变量为全局变量,所以在预解析时会把他们提升到最上面。所以结果就显而易见了。