本文主要讲解什么是Javascript作用域,以及作用域的分类及功能,通过代码讲解每种作用域的特点。

一:什么是作用域?

​ 作用域指的是一个变量的作用范围。

二:作用域分类

在JS中有两种作用域:

  • 全局作用域
  • 函数作用域

三:全局作用域

定义:直接编写在script 标签中的js代码,都在全局作用域中。

    <script type="text/javascript">
        var name = "tom";
        var age = 10;
    </script>

如上面的 name 和 age 变量,都是全局变量。

特点:

  • 全局作用域, 在页面打开时创建, 在页面关闭时销毁
  • 全局作用域中的变量都是全局变量, 在页面的任意部分都可以访问的到
  • 在全局作用域中有个全局对象window, 代表浏览器的窗口, 由浏览器创建给我们,可以直接使用。
  • 在全局作用域中创建的变量都会作为window对象的属性保存
  • 全局作用域中创建的函数都会作为window对象的方法保存
    <script type="text/javascript">
        var age = 10;
        var func = function () {
            console.log("this is a function")
        };
        //下面两句等同
        console.log(age);
        console.log(window.age)
        //下面两句也等同
        func();
        window.func();
    </script>

运行上面代码,发现加window和不加运行结果一致,其实全局变量age和func都是window对象的属性和方法。

注意:

    <script type="text/javascript">
        console.log(window.name);
        console.log(name);
    </script>

第一行打印语句输出:undefined(window对象已经存在,其属性不存在只会报undefined)

第二行打印语句输出:Uncaught ReferenceError: name is not defined (全局变量未声明则会出现异常)

为了验证第一条,我们运行下面的代码:

    <script type="text/javascript">
        var person = {
            age: 10,
            name: "Jerry"
        };
        console.log(person.age); //10
        console.log(person.email); //undefined
    </script>

总结:对象属性不存在会报:undefined。

关键点一:var关键字声明的全局变量声明提前。

使用var关键字声明的变量,会在所有的代码执行之前被声明,但是赋值并不会被提前,等运行到赋值语句时,才会赋值。

    <script type="text/javascript">
        console.log('a=' + a); //a=undefined
        var a = 123;
    </script>

它在内存中的执行类似于下面的代码逻辑:

    <script type="text/javascript">
        var a;
        console.log('a=' + a); //a=undefined
        a = 123;
    </script>

如果声明变量时没有使用var关键字,则变量不会被声明提前。因此下面的打印将会报错。

    <script type="text/javascript">
        console.log(name);
        name = "Tom";
    </script>

关键点二:函数声明形式函数的声明提前、函数表达式创建的函数不会被声明提前

​ 使用函数声明形式创建的函数function 函数名( ){ },它会在所有代码执行之前就被创建,优先级等同于var变量声明提前。 所以可以在函数声明之前调用函数。

    <script type="text/javascript">
        //调用
        func();

        //声明
        function func() {
            console.log("This is a function")
        }
    </script>

​ 使用函数表达式创建的函数, 不会被声明提前, 所以不能在声明之前被调用。下面的函数func的声明在最下面,它是window对象的变量,因此会提前声明,但是赋值(完整的函数体)必须要等到对应的代码处才行。

    <script type="text/javascript">
        //undefined
        console.log(func);

        //调用:Uncaught TypeError: func is not a function
        func();

        //声明
        var func = function () {
            console.log("This is a function")
        }
    </script>

四:函数作用域

JavaScript的函数作用域是指在函数内声明的所有变量在函数体内始终是可见的,可以在整个函数的范围内使用及复用,也就是说在函数体内变量声明之前就已经可用了(事实上在嵌套的作用域中也可以使用)。

  • 调用函数时创建函数的作用域,函数执行完毕后, 函数作用域销毁。
  • 每调用一次函数,就会创建一个新的函数作用域,他们之间是相互独立的。
  • 在函数作用域中可以访问到全局作用域的变量;在全局作用域中无法访问到函数作用域的变量。代码如下:
    <script type="text/javascript">
        var a = 10;
        function fun() {
            console.log('a=' + a);
        }
        fun(); // a=10
    </script>
    <script type="text/javascript">
        function fun() {
            var b = 20;
        }
        console.log(b); //报错Uncaught ReferenceError: b is not defined
    </script>
  • 当在函数作用域操作一个变量时,它会先在自身作用域中寻找, 如果找到了,就直接使用。如果没有找到, 则向上一级作用域中寻找,直到找到全局作用域。如果全局作用域中依然没有找到,则会报错ReferenceError。
    <script type="text/javascript">
        var b = 20;

        function fun() {
            var b = 123;
            console.log(b);
        }

        fun(); // 123 就近原则
    </script>
  • 在函数中要访问全局变量可以使用window对象
    <script type="text/javascript">
        var b = 20;

        function fun() {
            var b = 123;
            console.log(window.b);
        }

        fun(); // 20, 全局对象window访问全局变量
    </script>
  • 函数作用域也有声明提前的特性
    <script type="text/javascript">
        function fun() {
            console.log(b);
            var b = 123;
        }
        fun(); // undefined
    </script>

后台处理逻辑等同于:

    <script type="text/javascript">
        function fun() {
            var b;
            console.log(b);
            b = 123;
        }
    </script>
  • 定义形参就相当于在函数作用域中声明了变量
    <script type="text/javascript">
        function fun(a) {
            console.log(a); //形参a
        }
        fun(2); // 2
        fun(); // undefined 
    </script>
  • 在函数中, 一个变量在函数中没有声明,那么肯定是上层作用域的变量,上层也没有该变量,或直到全局作用域也没有该变量,使用时则报异常,不用var关键字声明的变量都会成为全局变量
    <script type="text/javascript">
        var age = 10;

        function fun() {
            console.log(age); //10
            age = 100;
        }
        fun();
        console.log(age); // 100
    </script>
    <script type="text/javascript">
        function fun() {
            console.log(age); //Uncaught
        ReferenceError: age is not defined
        }

        fun();
    </script>
    <script type="text/javascript">
        function fun() {
            age = 100;
        }

        fun();
        console.log(age); //100
    </script>

下面这段代码解释:函数体内第一行的t,首先看函数体内是否声明,如果没有声明,则找上层是否有t变量声明。但是本题中的第二行有var t的声明,此时声明提前,值为undefined,t = t + test的值也就为undefined,下一行 var t = 3;给t赋值为3,就打印3.

        var t = 10;

        function test(test) {
            t = t + test;
            var t = 3;
            console.log(t);
        }

        test(t);

指尖改变世界
27 声望6 粉丝

« 上一篇
Lambda表达式
下一篇 »
Java NIO 缓冲区