js重点——作用域——作用域分类(三)

  一、作用域可以分为全局作用域,局部作用域(函数作用域)和块级作用域。

  1、全局作用域

    代码在程序中的任何位置都能被访问到,window对象的内置属性都拥有全局作用域。

    <script>
        var a = 10;
        function fn() {
            b = 20;
            c = a + b;
        }
        fn();
        console.log(a, b, c); //10 20 30
    </script>

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

    函数作用域的含义是指,属于这个函数的全部变量都可以在整个函数的范围内使用及复用(包括嵌套的作用域中也可以使用)在固定的代码片段才能被访问;

    调用函数时创建函数作用域,函数执行完成后,函数作用域就销毁,每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立的;

    在函数作用域中可以访问到全局作用域的变量,但是在全局作用域中是访问不到函数作用域的变量;当函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用用,如果没有就向上一级作用域中寻找,直到找到全局作用域;

    在函数中要访问全局变量可以使用window对象。

    <script>
        var a = 10;
        function fn() {
            var a = 2;
            var b = 20;
            console.log(a + b); //22

            function fn1() {
                console.log(window.a+b); //30
            }
            fn1();
        }
        fn();
    </script>

  3、块级作用域

    在es6之前都是用var来声明变量,而js只有全局作用域和块级作用域.但es6新增的let和const可以声明块级作用域的变量。变量的声明应该距离使用的地方越近越好。并最大限度的本地化。

    a、let

    let声明的变量可以将变量绑定到所在的任意作用域中(通常是{...}内部),使用let声明的变量不会被提升。

  <script>
        for (var j = 0; j < 10; j++) {
            console.log(j);
        }

        for (let i = 0; i < 10; i++) {
            console.log(i);
        }
        console.log(i); // ReferenceError: i is not defined

</script>

    从上面的这一段代码中我们可以看出,我们只想在for䄸内部的上下文中使用变量但是实际上i可以在全局作用域中访问到,从而污染了整个作用域。所以我们用了let关键字,将j绑定到每一个迭代中,实现块作用域。

    b、const

    除了let以外,es6还引入了const,同样可以用来创建块作用域变量,但其值是固定的(常量)。之后任何试图修改值的操作都会引起错误。注意:const声明的是常量,之后的任何试图修改值的操作都是会引起错误的。它和let一样不可以重复的声明。

    <script>
        if (true) {
            var a = 2;
            const b = 3;
            // a=3;b=4 //Assignment to constant variable.
        }
        console.log(a);
        console.log(b); // ReferenceError: b is not defined
    </script>

  c、try-catch

 <script>
        {
            let a = 2;
            console.log(a); //2
        }
        console.log(a); //ReferenceError: a is not defined

        //在es6之前可以用try-catch
        try {
            throw 3; 
        } catch (b) {
            console.log(b)  //3
        }
        console.log(b); //ReferenceError: b is not defined
    </script>

  二、声明提升

    通过前面的知识我们得知,引擎会在解释sj代码前首先对其进和编译。编译阶段中的一部分工作就是找到所有的声明,并用合适的作用域将它们关联起来,包括变量和函数在内的所有声明都会在任何代码被执行前首先被处理。

   <script>
        var a = 2;
    </script>

    在以上代码中我们可以看出第一个定义声明在编译阶段由编译器进行,第二个赋值操作会被留在原地等待引擎在执行阶段执行。

        //对变量a的声明提升到最上面后,再执行代码时,输出2
        var a;
        a=2;
        console.log(a);//2

    声明从它们在代码中出现的位置被”移动“到了最上面,这个过程就叫做提升。每个作用域都会进行提升操作。

    不仅仅是变量声明可以提升,函数声明也有提升操作,但是函数表达式不能提升。

        fn();
        fn1();
        function fn() {
            console.log(1);
        }
        var fn1 = function () {
            console.log(1); //TypeError: fn1 is not a function
        }

猜你喜欢

转载自www.cnblogs.com/davina123/p/12021297.html
今日推荐