作用域
作用域:变量在某个范围内起作用,这个起作用的范围就称为作用域。在es6之前js只有全局作用域和局部作用域。根据作用域变量可分为全局变量和局部变量。
全局作用域和全局变量
全局作用域:作用于整个script标签,或者一个js文件。
全局变量:在全局作用域下声明的变量(在函数外部定义的变量)。
注意:如果在函数内部没有声明就直接赋值的变量也属于全局变量。
//a为全局变量
var a = 1;
console.log(a);
//b没有声明,直接赋值,为全局变量
function fn(){
b = 2;
}
//结果为2
console.log(b);
局部作用域和局部变量
局部作用域:作用于函数内部,变量名只在函数内部起作用。
局部变量:在局部作用域下定义的变量。
注意:函数的形参也可以看成局部变量。
//num1也可以看成局部变量
function fn(num1){
// a为局部变量
var a = 1;
}
fn(2);
全局变量和局部变量两者的区别
- 作用域不同;
- 执行效率不同:全局变量只有浏览器关闭的时候才销毁,占内存资源。局部变量当程序执行完毕就会被销毁,节约内存。
块级作用域
js是在es6新增的块级作用域。先省略(到es6特性的时候一起写)。。。
作用域链
内部函数可以访问外部函数的变量,采取链式查找来决定取哪个值,这种结构称为作用域链(就近原则)。
//全局变量
var a = 1;
//外部函数
function fn1(){
var a = 2;
//内部函数
function fn2(){
//输出 2
alert(a);
}
}
预解析
JS引擎运行JS代码分为两步:预解析 代码执行
- 预解析:JS引擎会把JS里所有的var 和 function 提升到当前作用域的最前面。
- 代码执行:按照代码书写的顺序从上往下执行。
预解析分为变量预解析(变量提升)和函数预解析(函数提升)
- 变量提升:把所有的变量声明提升到当前作用域的最前面,但不进行赋值操作。
- 函数提升:把所有的函数声明提升到当前作用域的最前面,但不调用函数。
变量提升的例子:
//运行结果:undefined
alert(num);
var num = 1;
//相当于执行了以下的代码
//进行变量提升但不赋值
var num;
//其余代码顺序不变
alert(num);
num = 1;
命名函数提升的例子:
//运行结果:1
function fn(){
alert(1);
}
fn();
//相当于执行了以下代码
//函数进行预解析
function fn(){
alert(1);
}
fn();
匿名函数变量提升的例子:
//结果报错
fn();
var fn = function(){
alert(1);
}
//相当于执行了以下代码
//因为匿名函数是以变量名进行定义和调用,所以先是进行变量解析(变量定义)
var fn;
//此时调用fn(),相当于在调用一个未赋值的变量,报错。
fn();
//再按顺序进行赋值
fn = function(){
alert(1);
}
预解析案例
案例1:
//运行结果 undefined
var num = 1;
fun();
function fun(){
alert(num);
var num = 20;
}
//相当于执行了以下代码
//首先进行全局作用域的变量和函数解析
var num;
funvtion fun(){
//在函数内部进行预解析
var num;
alert(num);
num = 20;
}
num = 1;
fun();
案例2
// 结果 undefined 2
var num = 1;
function fn(){
console.log(num);
var num = 2;
console.log(num);
}
fn();
//相当于以下代码
var num;
function fn(){
var num;
console.log(num);
num = 2;
console.log(num);
}
num = 1;
fn();
案例3
//运行结果 undefined 9
var a = 18;
fn();
function fn(){
var b = 9;
console.log(a);
console.log(b);
var a = '123';
}
案例4:注意集体声明的格式:var a = 1,b = 1,c = 1;如果是var a=b=c=1;则相当于var a = 1;b=1;c=1;b和c为直接赋值并未声明,为全局变量。
//运行结果 1 1 1 1 1 报错
fn();
console.log(c);
console.log(b);
console.log(a);
function fn(){
//b和c为全局变量
var a = b = c = 1;
console.log(a);
console.log(b);
console.log(c);
}
//相当于运行以下代码
function fn(){
var a;
a = b = c = 1;
console.log(a);
console.log(b);
console.log(c);
}
fn();
//c,b都为全局变量,a未在全局中定义
console.log(c);
console.log(b);
console.log(a);