0

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]

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

Aaron 2.9k
9月16日提问
3 个回答
0

已采纳

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 方法中,想详细了解可以去看一下。

0

在非严格模式下, 直接操作实参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,所以不会影响.

0

MDN 上的原话:

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

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

撰写答案

推广链接