0%

js作用域和预解析

今天又看了js基础教学视频,感觉这么好多num是真有意思啊(~才怪 ~)

js作用域

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

  1. 函数内部可以使用全局变量
  2. 函数外部不可以使用局部变量
  3. 当函数执行完毕,本作用域内的局部变量会销毁

1.全局作用域

  • 直接编写在script标签中的JS代码,都在全局作用域
  • 全局作用域在页面打开时创建,在页面关闭时销毁
  • 在全局作用域中有一个全局对象window,我们可以直接使用,它代表的是浏览器的窗口,它由浏览器创建,我们可以直接使用

因此

  • 在全局作用域中:

    创建的变量都会作为window对象的属性保存

    创建的函授都会作为window对象的方法保存

            var a = 1;
            b = 3                //隐式全局变量
            console.log(window.a);
            console.log(window.b);
            function fun(){
                console.log("我是fun函数");
            }
            window.fun();

2 局部作用域(函数作用域)

即函数体内部的作用域

词法作用域

var num = 123;
    function foo() {
    console.log( num );
}
foo();                //123

if ( false ) {
     var num1 = 123;
    }
console.log( num1 ); // undefiend

function f1(){
    var num2 = 123
}
console.log(num2)    //报错

变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,通过静态分析就能确定,因此词法作用域也叫做静态作用域。

词法作用域规则:

  • 函数允许访问函数外的数据.
  • 整个代码结构中只有函数可以限定作用域.
  • 作用域规则首先使用提升规则分析
  • 如果当前作用规则中有名字了, 就不考虑外面的名字

作用域链

有函数就可以制造作用域结构,在全局作用域内有函数,那么函数就构成了另一个作用域,函数中还有函数,那么就会在这个作用域中再诞生一个作用域。

将所有的作用域列出来,就可以有一个结构:函数内指向函数外的链式结构,称为作用域链

var num = 10
function f1(){
    var num = 20
    function f2(){
        var num = 30    
        function f3(){
            var num = 50
            console.log(num)
        }
        f3()
    }
    f2()
}
f1()

预解析(变量的声明提前和函数的声明提前)

变量的声明提前

使用var关键字,会在所有的代码执行之前被声明(但不会被赋值)

函数的声明提前

使用函数声明形式创建的函数function 函数(){}

它会在所有代码执行之前就被创建,所以我们可以在函数声明前调用

console.log("a = "+a);    //a = undefined

var a = 123;

fun();
function fun(){
    console.log("我是一个函数");

    console.log(num)    //undefined
    var num = 10
}

预解析是先提升functionvar,再提升var,即函数优先级比变量优先级高

f1()
console.log(b)        //9
console.log(c)        //9
console.log(a)        //报错,未声明
function f1(){
    var a = b = c = 9        //b、c是隐式全局变量
    console.log(a)    //9
    console.log(b)    //9
    console.log(c)    //9
 }