作用域:能够访问标识符的地方就叫作用域,比如函数的代码块内部和函数的代码块外部
规则1:函数内部的代码可以访问函数内部的标识符,也可以访问函数外部的标识符
规则2:函数外部可以访问函数外部的标识符,但是不能访问函数内部的标识符
案例
var total=0;
function increase(){
total=total+2
}
function decrease(){
total=total-2
}
increase() // 第一次调用increase函数,结果为2
increase() // 第二次调用increase函数,结果为4
decrease() // 第一次调用decrease函数,结果为2
console.log(total) // 打印2
如果在increase函数中声明一个变量total,那么结果会发生怎样的变化?
var total=0;
function increase(){
var total=0
total=total+2
}
function decrease(){
total=total-2
}
increase() // 第一次调用increase函数,结果为2
increase() // 第二次调用increase函数,结果为2
decrease() // 第一次调用decrease函数,结果为0
console.log(total) // 打印0
结论:函数的每一次调用都会重新执行该函数的所有代码
var a=10
function fn(){
//隐式操作:把var修饰的变量名提前声明=>var a;
console.log(a) // 打印声明了却没有赋值的变量a为undefined
a=40
var a=20
console.log(a)
}
console.log(a)
fn()
console.log(a)
结论:每一个作用域在运行时,js引擎会先把作用域内部的关键字隐式提前扫描,并声明
fn()
function fn(){
console.log(123)
}
// 打印123
问题:为什么先调用,后声明函数,仍然能打印出结果
结论:上述代码不会报错,而是打印结果,说明函数也会隐式提升。但是对象内部的方法不会隐式提升。
同名标识符提升问题
问题:在运行代码的时候,变量和函数同名时,是关键字var先隐式提升,还是函数先隐式提升?
结论:var先隐式提升。验证如下:
console.log(a) // 打印函数
var a=20;
function a(){
console.log(123)
}
//先隐式提升var关键字,在隐式提升函数
/*
隐式代码如下
var a;
function a(){};
console.log(a)
a=20
*/
//如果先隐式提升函数,结果就会打印undefined