作用域:变量可以起作用的范围和区域
不使用var声明的变量是全局变量,不推荐使用。
变量退出作用域之后会销毁,全局变量关闭网页或浏览器才会销毁
console.log(a); // undefined
var a = 2;
console.log(a); // a is not defined
f();
function f(){
console.log(12); //12
}
var f = 1;
function f(){
console.log(12); //12
}
// 由于函数提升在前,所以被变量声明替换了;
// 执行阶段,变量被复制为1,不再是一个函数,
f(); // f is not a function
注:不管是普通变量还是函数,尽量不要出现重名;
console.log(s); //undefined
var s = 2;
JavaScript代码的执行是由浏览器中的JavaScript解析器来执行的。 JavaScript解析器执行JavaScript代码的时候,分为两个过程:预解析(编译)过程和代码执行过程
预解析过程:
代码执行过程
变量的赋值,函数的调用,循环判断等,根据代码由上往下顺序执行;
var a = 25;
function abc (){
alert(a);//undefined
var a = 10;
}
abc();
// 如果变量和函数同名的话,函数优先做提升
console.log(a);
function a() {
console.log('aaaaa');
}
var a = 1;
console.log(a);
// 1、----------------
var num = 10;
fun();
function fun() {
console.log(num); //undefined
var num = 20;
}
// 2、----------------
var a = 18;
f1();
function f1() {
var b = 9;
console.log(a); //undefined
console.log(b); // 9
var a = '123';
}
变量的作用域是在定义时决定而不是执行时决定的,也就是说词法作用域取决于编译阶段,通过静态分析就能确定,因此词法作用域也叫做静态作用域。
在 js 中词法作用域规则:
var num = 123;
function foo() {
console.log( num );
}
foo();
if ( false ) {
var num = 123;
}
console.log( num ); // undefiend
也就是说:
函数内部可以访问函数外部的变量,但是函数外部不可以访问函数内部的变量;
函数内部如果有变量,则优先使用内部的变量,如果函数内部没有,才会使用函数外部的变量;
只有函数可以制造作用域结构, 那么只要是代码,就至少有一个作用域, 即全局作用域。凡是代码中有函数,那么这个函数就构成另一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。
将这样的所有的作用域列出来,可以有一个结构: 函数内指向函数外的链式结构。就称作作用域链。
var a = 1;
function fn1(){
function fn2(){
function fn3(){
console.log(a);
}
fn3();
}
fn2();
}
fn1();
var a = 1;
function fn1(){
var a = 2;
function fn2(){
var a = 3;
function fn3(){
console.log(a);
}
fn3();
}
fn2();
}
fn1();
总结: 函数内部是JS代码的局部作用域,函数外部是全局作用域,JS 代码的运行分为与解析阶段和执行阶段,变量的声明实在与解析阶段的,所以变量存在提升,而变量只在自己的作用域中起作用,但是自己作用域是可以访问上级作用域的;