zoukankan      html  css  js  c++  java
  • Javascript之旅——第一站:从变量说起

      工作这几年,js学的不是很好,正好周末有些闲时间,索性买本《js权威指南》,大名鼎鼎的犀牛书,好好的把js深入的看一看。买过这本

    书的第一印象就是贼厚,不过后面有一半部分都是参考手册。

    一:作用域

      说起变量第一个要说到的肯定就是作用域,正是因为不熟悉JS的作用域,往往就会把面向对象的作用域张冠李戴,毕竟有些东西总是习惯性

    的这样,但是并不是每次照搬都是可以的,那么下一个问题就来了,js到底是什么作用域,当然是函数作用域了,我们的浏览器就是一个被实例

    化的window对象,如果在window下定义一个name字段,那么name字段就具有window这个函数作用域,也就是在window下都是可以访问的,

    如果在window下定义一个function ctrip,然后里面再定义一个name,那么这个新定义的name只能在ctrip函数下通用,而老的name继续在

    window下通用,举个例子。

    从图中可以看出两点:

    1: 在window下定义了一个name,居然还可以在function下定义一个重名的name,这个在C#里面是不可想象的。

    2:在JS下就可以做到眼瞎,它只认自己的作用域,所以就出现了第一个"second",你可能觉得这个没有什么稀奇的地方,这是因为可能你还

        没有真正理解什么是函数作用域,解析器在执行ctrip的时候,第一件事情就是寻找ctrip下的所有局部变量,然后再执行后续语句,既然是先

        寻找,那么var name="second"这条语句定义在ctrip中任何位置都是可以的,下面我们把语句调换过来。

    可以看到在ctrip函数下,第一个console.log输出的是undefined,这个结果可以证实,确实做了第一件事情是收集到了name这个局部变量,可能

    有人说为什么没有变成”second“,那是因为初始化操作必须是逐语句执行,所以在ctrip函数中执行console.log(name)时,此时解析器只知道有一

    个未赋值的变量name,所以就console的时候就是undefined了。

    二:作用域链

      从上面的这个例子中我们也很清楚的知道了,在function中定义的变量只具有function范围内的作用域,同时我们也看到上面这个例子只是一层

    嵌套,window是个大的function,里面是一个ctrip的function,同样的道理也可以延伸到多层嵌套,比如三层,四层。。。。N层,这些层就形成了

    一个链式结构。

    从图中可以看到,我在ctrip下再定义了一个plane函数,这样的话就有三层了,输出的结果也是我们希望看到的,每层的name只在自己的作用域范围

    内生效,但是下面有一个问题来了,有一天我傻逼了,在定义plane的函数时,把 var name="third" 中的var忘记写了,那么这个时候,plane中的

    name到底是什么值呢? 是first还是second呢?

     1 var name="first";
     2 function ctrip(){
     3   var name="second";
     4   function plane(){
     5      name="third";
     6      console.log(name);
     7   }
     8   plane();
     9   console.log(name);
    10 }
    11 ctrip();
    12 console.log(name);

       现在就是考验你是否真的懂了作用域链,仔细想想会发现,当代码执行到plane函数中的name=”third“时,发现plane函数中并没有name这个局部

    变量,恰好代码又在ctrip这个大函数中,所以解析器就会回溯到ctrip函数中寻找name,发现果然有name,这个时候就把ctrip的name

    修改成了”third“。

    又有一天,我喝多了酒又傻逼了一回,在定义plane函数的时候,把name="third" 错写成了 nam="third"; 丢了一个e,你可以说是酒精的问题,

    又不是我代码的问题。那么这个时候解析器该怎么处理呢?同样的道理,在回溯时,发现ctrip没有,再回溯到顶层的window下,发现还是没有,

    这个时候解析器做了这样的处理,既然整个链中都没有,你又赋值了,我总不能给你报错,那多尴尬呀,就索性给你在window下隐式的定义一个

    nam变量,这个时候nam其实就是全局变量了。我们可以在window顶层console一下nam看看。

    好了,关于变量的东西也就这么多了,没什么稀奇的,理解了就没什么意思了。

  • 相关阅读:
    ApplicationContext
    消息队列种类
    Zookeeper的功能以及工作原理
    java多线程(1)模式 不可变对象
    dubbo容错,负载均衡,协议
    dubbo的底层原理
    消息事务处理
    多线程循环打印 abc
    Spring 事务管理
    文件上传和下载
  • 原文地址:https://www.cnblogs.com/huangxincheng/p/4116071.html
Copyright © 2011-2022 走看看