搜索

首页  >  问答  >  正文

javascript - 函数设置参数默认值的问题

var x = 1; 

function foo(x,y=function(){x=2;}){
    var x = 3;
    y();
    console.log(x); 
}
foo();

这段代码出现在阮一峰老师写的es6那本书,最后输出3,文字说明说y中的x和var x = 3;的x不是同一个x,这儿有点不理解。
然后把var x= 3 的var去掉,就能输出2,更不理解了。。。希望能有解答

巴扎黑巴扎黑2809 天前865

全部回复(7)我来回复

  • 女神的闺蜜爱上我

    女神的闺蜜爱上我2017-07-05 10:39:59

    这里其实是涉及到 ES6 默认参数引入的一个中间作用域。这个问题当初阮一峰也弄错过,当然这里是正确的。

    中间作用域的目的就是防止默认参数被函数里面的变量污染。默认参数本意是为了让参数有默认值,假如函数内部的变量还能提升上来,那么默认参数就没意义了。具体的解释和例子可以看文章。

    所以看回问题,

    var x = 1; 
    
    function foo (x2, y = function () { x = 2; }) {
        var x = 3;
        y();
        console.log(x); 
    }
    foo();

    这里有三个作用域,把 x 由外到里标记出来就是:

    var x1 = 1; 
    
    function foo (x2, y = function () { x2 = 2; console.log(x2); }) {
        var x3 = 3;
        y();
        console.log(x3); 
    }
    foo();
    console.log(x1);

    假如没有了参数的 x,那么标记出来就是:

    var x1 = 1; 
    
    function foo (y = function () { x1 = 2; console.log(x1); }) {
        var x2 = 3;
        y();
        console.log(x2); 
    }
    foo();
    console.log(x1);

    回复
    0
  • 阿神

    阿神2017-07-05 10:39:59

    y()修改的是foo函数的参数x,并非全局x。(这里你可以在y()调用后,console.log(x),可发现全局x还是1.)
    问题就简单了: 1) 当用var x = 3时,foo里面的console.log(x)打印的就是foo里的局部变量x,y()修改的只是参数x,所以最终输出是局部变量x = 3
    2)当不用var时,foo里的所有x都指向参数x,而用y()把参数x修改为2,最终输出2

    回复
    0
  • PHP中文网

    PHP中文网2017-07-05 10:39:59

    y 的默认值改变的是全局变量的x;
    把var x= 3 的var去掉,就能输出2 是因为在foo的作用域内找不到x,所以在往上寻找,找到全局变量x,此时已被赋值为2

    回复
    0
  • 天蓬老师

    天蓬老师2017-07-05 10:39:59

    这是局部变量和全局变量生命周期的区别,方法里面的var x = 3;是局部变量,两个变量同名,方法体里面会使用局部变量,不会使用全局变量,所以输出的是var x = 3;这个x的值;当你去掉var x = 3;的var,说明在方法里面没有另外定义局部变量,使用的是全局变量x,而你方法参数又把这个全局变量值修改为2,所以输出为2;

    回复
    0
  • 扔个三星炸死你

    扔个三星炸死你2017-07-05 10:39:59

    首先你要理解var操作符的定义,用var操作符定义的变量将成为定义该变量的作用域中的局部变量,也就是说,如果在函数中使用var定义一个变量,那么这个变量属于函数的一个局部变量,在函数退出时即被销毁,而不使用var直接定义的变量都将成为全局变量。
    另一个你要理解的概念是作用域链的问题,程序查找一个变量时,首先会在当前作用域内查找,若没有找到则顺着作用域链依次向上查找,遍历完都没有则报undefined。
    回到上面的代码,首先在全局作用域中利用var定义 x=1; x 即属于全局变量,接下来在函数foo内部定义了局部变量var x=3;X就属于函数的局部变量,接着执行y函数,对全局变量x进行修改赋值,这时x变为2,记住此时修改的是全局变量x而不是局部变量X,接下来打印x时,函数会依据作用域链先在函数内部查找x的值,找到x=3后即输出值,所以结果为3,若把var x=3的var去掉,则x变为全局变量,修改x就如同y函数中x赋值一样,这时只存在一个全局变量x,按照代码执行顺序,内部先修改全局变量X为3,然后y函数修改全局变量x为2,打印时,顺着作用域链,在函数内部没有找到x值,则接着在全局作用域中查找,此时X为2,所以结果为2

    回复
    0
  • 扔个三星炸死你

    扔个三星炸死你2017-07-05 10:39:59

    雷雷

    回复
    0
  • 为情所困

    为情所困2017-07-05 10:39:59

    回复
    0
  • 取消回复