• 3.4k

es6默认值问题

es6在函数参数中添加默认值,给其中一个参数赋值,有无默认值为什么arguments的输出结果会受到影响?

const fn1 = function(a = 7,b = 8, c = 9){
    a = 10;
    console.log(arguments)
}
const fn2 = function(a, b, c){
    a = 10;
    console.log(arguments)
}
fn1(1,2,3); //    输出结果:[1,2,3]
fn2(1,2,3); //    输出结果:[10,2,3]

这个输出结果我很费解,求告知。

阅读 600
评论
    3 个回答
    • 9.1k

    javascript 里的 arguments 分两种,mapped 和 unmapped 。

    对于 mapped arguments ,对 arguments 的元素会映射到实参。于是实参赋值会影响 arguments, 对 arguments 的元素赋值会影响实参。

    unmapped arguments 没有这种映射,对 arguments 以及对参数的赋值互不影响。

    只有在非严格模式,简单参数列表的时候,才提供 mapped arguments 。其他时候,arguments 都是 unmapped 。所谓简单参数列表,指参数列表不包含解构参数,rest 参数(, ...a)),以及默认值。

    所以,正是默认值影响了 arguments 的类型。没有默认值时,arguments 是 mapped ;有了默认值,arguments 是 unmapped 。从而导致了对实参的赋值(a=10;) 对 arguments 内容带来了不同的影响。

    arguments 构建的具体算法包含在 ecma262 的 FunctionDeclarationInstantiation 方法中,想详细了解可以去看一下。

      • 1.3k

      在非严格模式下, 直接操作实参a b c会改变arguments的值,

      // 加个严格模式
      'use strict'
      
      const fn2 = function(a, b, c){
          a = 10;
          console.log(arguments)
      }
      fn2(1,2,3); //    输出结果:[1,2,3]

      关于fn1,可以用babel测试%7B%0A%20%20%20%20a%20%3D%2010%3B%0A%20%20%20%20console.log(arguments)%0A%7D)查看

      $traceurRuntime.ModuleStore.getAnonymousModule(function() {
        "use strict";
        var fn1 = function() {
          var a = arguments[0] !== (void 0) ? arguments[0] : 7;
          var b = arguments[1] !== (void 0) ? arguments[1] : 8;
          var c = arguments[2] !== (void 0) ? arguments[2] : 9;
          a = 10;
          console.log(arguments);
        };
        return {};
      });
      //# sourceURL=traceured.js

      被转化成了 arguments赋值的形式,脱离了argument,所以不会影响.

        MDN 上的原话:

        当非严格模式中的函数有包含剩余参数、默认参数和解构赋值,
        那么arguments对象中的值不会跟踪参数的值(反之亦然)。
        相反, arguments反映了调用时提供的参数

        fn1 满足条件1.非严格模式 2.包含默认参数,所以,arguments 的值和参数的值相互独立。
        fn2 没有包含剩余参数、默认参数或结构赋值,所以是相反的结果,arguments 的值和参数的值相互影响。

          撰写回答

          登录后参与交流、获取后续更新提醒