• 认识Javascript中的作用域和作用域链


    作用域

    只要写过java或者c#等语言的同学来说,相信一定能理解作用域的概念,在作用域的范围中,我们可以使用这个作用域的变量,对这个变量进行各种操作。可是,当使用Javascript的时候,相信很多的同学都会遇到迷惑的时候。

    例如,我们看一个常用并经典的案例。

    var name = '张三';
    
    function fun() {
        console.log(name);
        var name = '李四';
    }
    fun()

    对于初识javascript的同学来说可能会认为打印的是“张三”,不过我们惊奇的发现打印的是“undefined”,下面我们来分析分析为什么会出现这样的情况。

    首先,我们需要认识三个概念:全局变量、局部变量以及变量提升

    全局变量

    在全局定义的变量为全局变量,在这个作用环境中的所有函数对象都是可以调用到全部变量。

    局部变量

    顾名思义,局部变量即定义在函数内部的变量。他的作用环境局限在变量所在的局部环境中。

    变量提升

    在javascript中,函数和变量声明都会被提升到函数的顶部。通俗的来说就是我们可以先使用变量,然后再声明函数。

    接下来,我们看看下面几个例子:

    例1:

    var name = "张三"
    function fun() {
        console.log(name);
    }
    fun()

    显而易见,这次我们的打印结果是  “张三”。

    现在我们看第二个例子:

    例2:

    var name = "张三"
    function fun() {
        console.log(name);
    }
    fun()

    这次的结果同样是显而易见的,打印了 “张三”。

    上面两个例子我们认识了全局变量和局部变量,现在我们再看看第三个例子。

    例3:

    function fun() {
        console.log(name)
        var name = "李四";
        console.log(name);
    }
    fun()

    这里就需要我们用到变量提升的概念,上面我们提到,javascript对函数和变量声明提升到函数头部,所以在执行第一次打印之前,name这个变量已经被环境帮我们声明了,但是环境并不会帮我们赋值,所以,第一次会打印undefined,然后,第二次打印“李四”。

    上面的程序我们换一种写法或许更好理解。

    function fun() {
        var name = undefined;
        console.log(name)
        name = "李四";
        console.log(name);
    }
    fun()

    现在我们就可以来理解下最开始说的这个例子了。

    var name = '张三';
    
    function fun() {
        console.log(name);
        var name = '李四';
    }
    fun()

    1. 在全部环境中定义了全局变量 name="张三";

    2. 在局部环境中定义了name=“李四”,所以局部变量和全局变量名字相同的时候,会优先获取局部变量的值;

    3. 由于我们打印name变量是在定义name之前,所以,根据变量提升的特性,所以这里我们会打印 undefined。

    相信通过前面几个例子,我们对作用域已经有了一些了解,下面就对作用域进行一下总结。

    概念:作用域是一种规则,是 javascript中所有可访问的变量的集合(函数,对象都是变量)。

    作用:我们通过作用域可以访问权限内的所有变量,并进行相应操作。

    作用域链

    对于理解了javascript中的作用域之后,作用域链就是一个比较容易理解的概念。同样,我们也通过一个例子来看。

    var age = 18;
    
    function a() {
        var sex = 'sex';
    
        b();
        function b() {
            var color = 'green';
            
            console.log({age, sex, color})
        }
    }
    
    a();

    相信大家都能一样看出这段程序的输出结果是{age: 18, sex: "sex", color: "green"},虽然程序简单,不过却是我们理解作用域链的一个好例子。

    我们再输出的时候会打印age,sex,color三个变量。

    对于color变量来说,本来就在当前执行函数b的作用域内,所以color变量的寻找路径是b.color;

    对于sex变量来说,在执行函数b的作用域中找不到sex变量,所以,他会沿着b函数的作用域链找到函数a的作用域,所以sex变量的寻找路径是 b > a.sex;

    对于age变量来说,执行函数b中找不到,沿着作用域链找到a函数的作用域依然没找到,就会一直沿着作用域链找到window环境,在这里找到了变量age,所以age变量的寻找路径是b>a>window.age

    通过上一个例子,我们应该可以清楚的认识作用域链是什么样的存在,同样我们也总结一下。

    概念:作用域链是作用域的具体实现,通过作用域链可以确定变量被访问的权限。

    作用:可以通过作用域链,了解我们在当前执行环境可以访问哪些变量。

    浅陋见识,不足之处,请大神指正。

  • 相关阅读:
    iis aspx常见错误 没有对“C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/Temporary ASP.NET Files”的写访问权限。
    Windows 下 Apache HTTP Server 安装、配置以及与 Tomcat 的整合(附图)
    Xstudio+Bugzilla
    测试管理工具列表大全
    bitmap详细介绍
    Android学习绘制图形
    PorterDuff.Mode
    盒模型及文本溢出
    css属性继承
    CSS层叠样式
  • 原文地址:https://www.cnblogs.com/heshuaiblog/p/13986401.html
Copyright © 2020-2023  润新知