我们可以设置持久性默认参数,这些参数在显式更

时间:2017-04-18 07:54:45

标签: javascript ecmascript-6

以下是一个函数fn,其中预期结果是abc在每次fn调用时定义的结果,是否为对象参数是否通过。如果传递了设置属性的对象,则只应为该对象设置属性。

const fn = (opts = {a:1, b:2, c:3}) => console.log(opts);

在没有参数的情况下调用时,结果为

fn() // {a: 1, b: 2, c: 3}

使用参数调用时,例如{b:7},预期结果为

fn({b:7}) // {a: 1, b: 7, c: 3}

然而,实际结果是

fn({b:7}) // {b: 7}

能够通过定义函数外部的对象并在函数体中使用Object.assign()来获得预期结果

const settings = {a: 1, b: 2, c: 3};
const fn = opts => {opts = Object.assign({}, settings, opts); console.log(opts)}
fn({b: 7}) // {a: 1, b: 7, c: 3}
fn(); // {a: 1, b: 2, c: 3}
/*
  // does not log error; does not return expected result
  const fn = (opts = Object.assign({}, settings, opts)) => console.log(opts)
 
*/

上述结果是否可以仅使用默认参数来实现,而无需在函数参数之外或函数体内定义要引用的对象?

4 个答案:

答案 0 :(得分:3)

也许我误解了这个问题,但您似乎正在寻找每个单独属性的默认初始化程序。为此,你必须使用解构:

const fn = ({a = 1, b = 2, c = 3} = {}) => console.log({a, b, c});

如果您想保留任意属性,而不仅仅是您预先知道的属性,您可能会对允许您编写的object rest/spread properties proposal感兴趣

const fn = ({a = 1, b = 2, c = 3, ...opts} = {}) => console.log({a, b, c, ...opts});
  

单个对象引用的opts变量是否可以仅使用默认参数来实现,而无需在函数参数之外或函数体内定义要引用的对象?

没有。参数声明只能使用(部分)参数初始化变量,并且当没有传递undefined参数(部分)时,可能(作为语法糖)使用默认值。他们无法进行无条件计算并根据结果创建变量 - 这是您尝试在此处实现的。

你应该使用函数体。

答案 1 :(得分:2)

没有

可以做的最好的是你自己的答案或者:

const fn = (default_parameters) => { 
  default_parameters = Object.assign({}, {a: 1, b: 2, c: 3},default_parameters);
  console.log('These are the parameters:');
  console.log(default_parameters);
}

    fn();

    fn({b: 7});

    fn({g: 9, x: 10});

默认参数块仅在未设置值时执行,因此您自己的答案是最好的,即使用两个参数

您可以通过创建一个代码块来说服自己,如果执行该代码块并且测试传递参数是否有效(以显示代码块未执行)并且测试未传递参数失败(显示代码) block仅在没有传递参数时执行。

这应该清楚地表明,任何传递的参数都会阻止对默认参数进行评估。

    const fn = (default_parameters = (default_parameters = Object.assign({}, {a: 1, b: 2, c: 3},default_parameters))) => { 
      
      console.log('These are the parameters:');
      console.log(default_parameters);
    }

        fn({b: 7});
        
        fn();

        fn({g: 9, x: 10});

答案 2 :(得分:0)

我们可以将fn设置为返回箭头函数表达式的变量。当调用set abc和rest参数时,使用新对象的spread元素引用,该函数在调用函数时返回。

const fn = ((...opts) => ({a:1,b:2,c:3, ...opts.pop()}));

let opts = fn();

console.log(opts);

opts = fn({b: 7});

console.log(opts);

opts = fn({g: 9, x: 10});

console.log(opts);

使用rest元素,Object.assign(),spread元素,Array.prototype.map(),将不是对象的元素设置为反映数组中元素索引的属性值。

const fn = ((...opts) => Object.assign({a:1,b:2,c:3}, ...opts.map((prop, index) =>
             prop && typeof prop === "object" && !Array.isArray(prop) 
             ? prop 
             : {[index]:prop})) 
           );

let opts = fn([2,3], ...[44, "a", {b:7}, {g:8, z: 9}, null, void 0]);

console.log(opts);

答案 3 :(得分:-1)

虽然OP的代码使用单个默认参数,但在找到或开发仅使用单个参数的程序之前,我们可以利用设置两个默认参数来达到预期的结果。

第一个参数默认为普通对象,在第二个默认参数,我们将参数标识符从第一个参数传递给Object.assign(),跟随问题模式。

我们引用函数fn的第二个参数标识符来获取没有参数时调用的默认参数;当第一个参数调用属性设置为在第一个参数和默认参数传递的对象的属性时,前者在结果对象中覆盖后者。

const fn = (__ = {}, opts = Object.assign({}, {a: 1, b: 2, c: 3}, __)) => 
             console.log(opts);

fn();

fn({b: 7});

fn({g: 9, x: 10});