• 全局变量名、局部变量名和形参名冲突时,覆盖情况


    以前错误的认为,全局变量名、局部变量名和形参名相同时,全局变量(也就是外部变量)被形参覆盖,形参被局部变量覆盖。

    今天发现这样理解并不对。比如

    function foo(num){
      var num;
      console.log(num);  
    }
    foo(1)   //  1
    
    //如果错误的理解为局部变量会覆盖形参的话,会认为会输出undefined

    那事实是什么呢。实际上变量名冲突分两种,一种是函数外的变量和函数里的局部变量的冲突,一种是函数内部的冲突。

    第一种冲突,我把它理解为是作用域链的上游(最上游是全局对象的命名空间)会被下游函数的局部变量覆盖。

    其实我觉得这就是一种继承关系,好比原型链里离目标对象近的新的方法覆盖远的旧的方法,甚至是好比HTML/CSS里字体、颜色等属性的继承。

    只不过这里继承的是一个上下文环境。

    它们都有一个特点,自己有,用自己的;自己没有,用父级的;父级没有,再逐级向上。

    //和HTML/CSS属性继承不同的是,JS作用域链还涉及变量/函数声明
    
    //简单说,就是子元素一旦声明了变量,不管有没有赋值,都算做是有自己的了
    //也就不会操作到父级了
    
    var b;
    function foo2() {
        console.log(b);
        var b;
    }
    foo2();//undefined

    第二中是函数内部的冲突,即同一作用域内的冲突。

    形参和局部变量其实就是同一作用域的。只不过JS里的形参省略了声明(像是Java就需要和变量一样做类型声明)。

    而在JS里有:同一作用域,重复申明但不赋值,不会对变量有影响

    var a=1;
    console.log(a);  //1
    var a;
    console.log(a);  //1

    这也就解释了,为什么局部变量申明但不赋值,不影响形参。

    或许你会有我之前的另一种猜测,局部变量声明但不赋值,不会覆盖形参,但赋值了不是改变形参,而是覆盖。

    那我们再看看这个

    var b;
    function foo2(b) {
        var b=2;
        console.log(b);
        console.log(arguments[0]);
    }
    foo2(1);
    
    //假如是局部变量名覆盖形参名的话,那应该打印'2 1'
    //而事实是'2 2'
    //所以其实局部变量和形参冲突,就是重复定义个变量
    //所以我觉得其实可以把形参理解为一个特殊的局部变量
    //只不过它在函数定义时被申明,而且申明的var 被省略
    function foo2(var b){
    }
  • 相关阅读:
    CentOS 7.3 CDH 5.10.0 Druid0.12.4安装记录
    cloudera manager卸载流程
    CDH5.10.0 离线安装(共3节点) 转
    CentOS 7 安装Httpd(转)
    CentOS下MySQL的彻底卸载
    CentOS7 修改主机名
    sendEvent()
    QSignalMapper Class
    ubuntu12.04开启虚拟机的unity模式
    BCM_I2C函数更改
  • 原文地址:https://www.cnblogs.com/liyan-web/p/5911295.html
Copyright © 2020-2023  润新知