JavaScript——作用域

JavaScript/前端
403
0
0
2022-12-02

作用域

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

简单理解:就是代码名字(变量)在某个范围内起作用和效果。

JS的作用域(es6)之前:全局作用域和局部作用域。

全局作用域:整个script标签或者是一个单独的js文件。

局部作用域:在函数内部就是局部作用域(函数作用域),这个代码的名字只在函数内部起效果和作用。

变量的作用域

根据作用域的不同,我们变量分为全局变量和局部变量。

全局变量:在全局作用域下声明的变量。

注意:如果在函数内部没有声明,直接赋值的变量也属于全局变量。

var num = 10;//num就是一个全局变量

局部变量:在局部作用域下声明的变量,或者说在函数内部的变量。

注意:函数的形参也可以看做是局部变量。

function fun() {
    var num1 = 10; //num1就是局部变量,只在函数内部使用
}

全局变量可以在函数内部使用,局部变量不可以在函数外部使用。

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

  • 全局变量只有浏览器关闭的时候才会销毁,比较占内存资源。
  • 局部变量当我们程序执行完毕就会销毁,比较节约内存资源。

作用域链

只要是代码就有一个作用域,写在函数内部的叫局部作用域,如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域,根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定那些数据能被内部函数访问,就称为作用域链。

作用域链:内部函数访问外部函数的变量,采取的是链式查找的方式来决定取那个值,这种结构我们称为作用域链。(就近原则)

案例:结果是几?

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); //a的值为4 
            console.log(b); //b的值为22
        }
    }
}
fn1();

预解析

JavaScript代码是由浏览器中的JavaScript解析取来执行的。

JavaScript解析器在运行JavaScript代码的时候分为两步:预解析和代码执行。

  • 预解析:js引擎会把js里面的所有var还要function提升到当前作用域的最前面。
  • 代码执行:按照代码书写的顺序从上往下执行。

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

  • 变量提升:就是把所有的变量声明提升到当前的作用域前面,不提升赋值操作。
console.log(num); //undefined
var num = 10;
//相当于执行了以下代码:
var num;
console.log(num);
num = 10;
fun();
var fun = function() {
        console.log(11);
    }
    //相当于执行了以下代码
var fun;
fun();
fun = function() {
    console.log(11);
}
  • 函数提升:就是把所有的函数声明提升到当前作用域的最前面,不调用函数。

注意:函数表达式调用必须写在函数表达式的下面。

案例:

var num = 10;

function fn() {
    console.log(num);
    var num = 20;
    console.log(num);
}
fn();
//相当于以下代码:
var num;

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