admin 管理员组

文章数量: 887007

JS第九讲

九、作用域和预解析

第一部分:作用域

(一)作用域导读

 

(二)JS作用域和变量

  1. 作用域

    通常来说,一段代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性代码范围就是这个名字的作用域.作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突.

    全局作用域:整个script标签中都可以用,或者是一个单独的js文件

    局部作用域:在函数内部就是局部作用域.

    局部作用域定义的变量,名字可以与全局变量重复,不会引发冲突,优先使用局部变量.

    根据作用域的不同,变量可分为两种,全局变量和局部变量.

  1. 全局变量和局部变量

    在全局直接声明的变量是全局变量.

    全局变量在代码任何位置都可以使用.

    注意:在函数内部没有声明直接赋值的变量也是全局变量

    函数的形参是局部变量.

  1. 从执行效率看全局变量和局部变量

    全局变量只有浏览器关闭的时候才会销毁,比较占内存资源

    局部变量当程序执行完毕就会销毁,比较节约内存资源.

  2. JS没有块级作用域

    在ES6以前没有块级作用域,ES6以后才有.

    块级作用域:

    if(xxx){var num=10;
    }
    ​
    for(xxx){var num=10;
    }

    在JS中,这两种语句里定义的变量视为全局变量.

(三)作用域链

只要是代码,就至少有一个作用域.

写在函数内部的是局部作用域.而如果函数中还有函数,那么在这个作用域中就又可以诞生出一个作用域.

函数中可以定义函数:

var num=10;
function fn(){ //外部函数var num=20;function fun(){ //内部函数console.log(num); //输出结果为20}fun(); 
}

外面的叫外部函数,里面的叫内部函数

根据在内部函数可以访问外部函数作用域这种机制,用链式查找决定那些数据能被内部函数访问,就称为作用域链.

简单来说:就近原则

(四)作用域链案例

var num=456;
function f1(){ //外部函数var num=123;function f2(){ //内部函数console.log(num); //输出结果为20}fun(); 
}
fn();

作用域链:

 

小技巧:站在目标出发,一层一层往外找,找到的第一个目标,就是答案.

第二部分 预解析

(一)预解析导读

 

(二)预解析

JS代码是通过浏览器中的UJS解析器来执行的.JS解析器在运行JS代码的时候分两步:预解析和代码执行

  1. 预解析,JS引擎会把js里面所有的var还有function提升到当前作用域的最前面.

  1. 代码执行,按照代码书写顺序从上向下执行.

预解析分为变量预解析(变量提升)和函数预解析(函数提升)

  1. 变量提升:把所有的变量声明提升到当前的作用域最前面,只提升变量声明,不提升赋值操作.

    console.log(num);
    var num=10;

    相当于是:

    var num;
    console.log(num);
    var num=10;

    而:

    fun();
    var fun=fuction(){console.log(22);
    }

    相当于以下代码:

    var fun;
    fun();
    fun=fuction(){console.log(22);
    }

    调用的fun还是变量,而不是函数,所以会报错.

  2. 函数提升:把函数声明提升到当前作用域的最前面.不调用函数.

    只适用于直接定义的函数,不适用于函数表达式.

(三)预解析案例

案例1:

var num=10;
fun();
function fun(){console.log(num);var num=20;
}

问,输出的值是多少?

相当于执行了下面的操作:

var num;
num=10;
fun();
function fun(){var num;console.log(num);num=20;
}

所以输出为:undefined.

案例2:

var num=10;
function fn(){console.log(num);var num=20;console.log(num);
}
fn();

输出结果为多少?

很简单,undefined 20.

案例3:

f1();
console.log(c);
console.log(b);
console.log(a);
function f1(){var a=b=c=9; //相当于: var a=9; b=9; c=9; b和c前没有varconsole.log(a);console.log(b);console.log(c);
} 

输出结果为多少?

预解析:

function f1(){var a;a=9;b=9;c=9; //这里的b和c直接赋值,没有声明,当全局变量看!!!console.log(a);console.log(b);console.log(c);
} 
f1();
console.log(c);
console.log(b);
console.log(a);

所以结果为:9 9 9 9 9 报错.

本文标签: JS第九讲