为 JavaScript 函数设置默认参数值

问:

我希望 JavaScript 函数具有我设置默认值的可选参数,如果未定义该值(如果传递该值则忽略该值)。在 Ruby 中,你可以这样做:

def read_file(file, delete_after = false)
  # code
end

这在 JavaScript 中有效吗?

function read_file(file, delete_after = false) {
  // Code
}

答1:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

从 ES6/ES2015 开始,默认参数在语言规范中。

function read_file(file, delete_after = false) {
  // Code
}

只是工作。

参考:Default Parameters - MDN

如果未传递任何值或未定义,则默认函数参数允许使用默认值初始化形式参数。

在 ES6 中,您可以simulate default named parameters via destructuring:

// the `= {}` below lets you call the function without any parameters
function myFor({ start = 5, end = 1, step = -1 } = {}) { // (A)
    // Use the variables `start`, `end` and `step` here
    ···
}

// sample call using an object
myFor({ start: 3, end: 0 });

// also OK
myFor();
myFor({});

ES2015 之前,

有很多方法,但这是我的首选方法——它可以让你传入任何你想要的东西,包括 false 或 null。 (typeof null == “object”)

function foo(a, b) {
  a = typeof a !== 'undefined' ? a : 42;
  b = typeof b !== 'undefined' ? b : 'default_b';
  ...
}

您也可以将其封装为:function defaultFor(arg, val) { return typeof arg !== 'undefined' ? arg : val; },然后您可以将其称为 a = defaultFor(a, 42);

@SiPlus 并且您在尝试使用 undefined 对象时免费获得了额外的引用错误:p 即使它可能适用于某些浏览器并且可能更快,但 null 仍然是一个对象,而 undefined 是对原始的引用试图告诉这里没有任何东西的类型,甚至没有 null。请参阅此处,简而言之这两种情况:JavaScript/Reference/Global_Objects/undefined。

如果您检查对象的属性,则 typeof 是多余的。 function foo(data) { var bar = data.bar !== undefined ? data.bar : 'default'; } 这不会引发引用错误并且简洁。

我知道这真的很小,但我不喜欢您在未定义这些参数时如何分配 a = a 和 b = b。此外,对于未来的维护者来说,条件有点复杂的三元运算符可能难以阅读。我更喜欢以下语法:if (typeof a == 'undefined') a = 42 - 没有不必要的分配加上更容易阅读。

有什么理由使用 typeof?只做 a === undefined 似乎更简单。另外,如果您拼写错误 undefined 而不是将其放入字符串中,那么您会收到参考错误。

答2:

huntsbot.com – 高效赚钱,自由工作

function read_file(file, delete_after) {
    delete_after = delete_after || "my default here";
    //rest of code
}

如果它不是 falsey 值,则将 delete_after 的值分配给 delete_after,否则分配字符串 “my default here”。有关更多详细信息,请查看 Doug Crockford’s survey of the language and check out the section on Operators。

如果您想传入 falsey 值,即 false、null、undefined、0 或 “”,则此方法不起作用。如果您需要传入 falsey 值,则需要使用 Tom Ritter’s answer 中的方法。

在处理函数的多个参数时,允许使用者在对象中传递参数参数然后将这些值与包含函数默认值的对象合并通常很有用

function read_file(values) {
    values = merge({ 
        delete_after : "my default here"
    }, values || {});

    // rest of code
}

// simple implementation based on $.extend() from jQuery
function merge() {
    var obj, name, copy,
        target = arguments[0] || {},
        i = 1,
        length = arguments.length;

    for (; i < length; i++) {
        if ((obj = arguments[i]) != null) {
            for (name in obj) {
                copy = obj[name];

                if (target === copy) {
                    continue;
                }
                else if (copy !== undefined) {
                    target[name] = copy;
                }
            }
        }
    }

    return target;
};

使用

// will use the default delete_after value
read_file({ file: "my file" }); 

// will override default delete_after value
read_file({ file: "my file", delete_after: "my value" }); 

我觉得这还不够,因为我可能想传入 false。

我发现它适用于大多数情况

因为它不适用于虚假值,所以它可能会造成维护噩梦。在有更健壮的方法可用的情况下,应该避免之前一直传递真实值并突然失败的代码,因为传入了虚假值。

在这种情况下,为什么 delete_after 没有得到表达式 delete_after || "my default value" 的布尔结果?

或者,您可以只默认为 false 值——这通常是一个很好的默认值(例如,布尔值为 false,字符串为空字符串,数字为 0 等)——在这种情况下,什么并不重要通过了。

答3:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

我发现像这样简单的东西更简洁易读。

function pick(arg, def) {
   return (typeof arg == 'undefined' ? def : arg);
}

function myFunc(x) {
  x = pick(x, 'my default');
} 

更新:如果您已经在使用 underscore.js,我发现使用 _.defaults(iceCream, {flavor: "vanilla", sprinkles: "lots"}); 会更好。使用此答案中所示的全局命名空间被许多人认为是一种不好的做法。如果不想使用下划线,您也可以考虑为这个常见任务滚动您自己的实用程序(例如 util.default(arg, "defaul value")),但我最终还是迟早会使用下划线,没有必要重新发明轮子。

我实际上推荐这个,我使用它并称之为“por”,代表“参数或”

不要说 typeof arg == 'undefined',而是说 arg === undefined

@OsamaBinLogin 你所说的对当前的 JS 来说是正确的——旧的测试仍然存在,因为在某些浏览器上,它曾经可以用其他值覆盖 undefined,导致测试失败。

@Alnitak:仍然可以覆盖 undefined。因此,使用 typeof 和 'undefined' 仍然是一个好主意。

答4:

huntsbot.com – 高效赚钱,自由工作

在 ECMAScript 6 中,您实际上将能够准确地编写您所拥有的内容:

function read_file(file, delete_after = false) {
  // Code
}

如果它不存在或 undefined,这会将 delete_after 设置为 false。您现在可以通过 Babel 等转译器使用 ES6 特性。

See the MDN article for more information。

等待浏览器获取 ECMAScript 6

Babel 会将其转译成什么?

@harryg:babeljs.io/repl/…

这是 ES6 kangax.github.io/compat-table/es6/#default_function_parameters 的兼容性表,不幸的是,这种语法尚不支持。

Edge14 和当前的 Chrome 和 Opera 现在支持它,以及去年的 FF ......现在正在等待 Safari,它在当前测试版中支持它,所以希望在大约 4 个月内所有浏览器的最新版本都会支持它。然后你只需要等待你的用户真正更新他们的浏览器(或推动他们这样做。)

答5:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

默认参数值

使用 ES6,您可能会做 JavaScript 中最常见的习惯用法之一,即为函数参数设置默认值。我们多年来这样做的方式应该看起来很熟悉:

function foo(x,y) {
 x = x || 11;
 y = y || 31;
 console.log( x + y );
}
foo(); // 42
foo( 5, 6 ); // 11
foo( 5 ); // 36
foo( null, 6 ); // 17

这种模式是最常用的,但是当我们传递像这样的值时很危险

foo(0, 42)
foo( 0, 42 ); // 53 <-- Oops, not 42

为什么?因为 0 is falsy 和 x || 11 results in 11,而不是直接传入的 0。为了解决这个问题,有些人会改写更详细的检查,如下所示:

function foo(x,y) {
 x = (x !== undefined) ? x : 11;
 y = (y !== undefined) ? y : 31;
 console.log( x + y );
}
foo( 0, 42 ); // 42
foo( undefined, 6 ); // 17

我们现在可以检查从 ES6 开始添加的一个很好的有用语法,以简化将默认值分配给缺失参数的过程:

function foo(x = 11, y = 31) {
 console.log( x + y );
}

foo(); // 42
foo( 5, 6 ); // 11
foo( 0, 42 ); // 42
foo( 5 ); // 36
foo( 5, undefined ); // 36 <-- `undefined` is missing
foo( 5, null ); // 5 <-- null coerces to `0`
foo( undefined, 6 ); // 17 <-- `undefined` is missing
foo( null, 6 ); // 6 <-- null coerces to `0`

函数声明中的 x = 11 更像 x !== undefined ? x : 11 而不是更常见的习语 x || 11

默认值表达式

Function 默认值可以不仅仅是简单的值,例如 31;它们可以是任何有效的表达式,甚至是 function call:

function bar(val) {
 console.log( "bar called!" );
 return y + val;
}
function foo(x = y + 3, z = bar( x )) {
 console.log( x, z );
}
var y = 5;
foo(); // "bar called"
 // 8 13
foo( 10 ); // "bar called"
 // 10 15
y = 6;
foo( undefined, 10 ); // 9 10

如您所见,默认值表达式是惰性求值的,这意味着它们仅在需要时运行——即,当参数的参数被省略或未定义时。

默认值表达式甚至可以是内联函数表达式调用 — 通常称为立即调用函数表达式 (IIFE):

function foo( x =
 (function(v){ return v + 11; })( 31 )
) {
 console.log( x );
}
foo(); // 42

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

答6:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

该解决方案在 js 中对我有用:

function read_file(file, delete_after) {
    delete_after = delete_after || false;
    // Code
}

如果 delete_after 是 0 或 null 会发生什么?对于这些情况,它将无法正常工作。

@StephanBijzitter 仅在某些情况下才是正确的。但是,如果您只想使用默认值来取消设置值,那么这是行不通的,因为 0 或 null !=== false。

@Rutrus:我不明白你刚才说的话。

delete_after = delete_after === undefined ? false : delete_after 呢?

答7:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

我强烈建议在 javascript 中使用默认参数值时要格外小心。当与 forEach、map 和 reduce 等高阶函数结合使用时,它通常会产生错误。例如,考虑这行代码:

['1', '2', '3'].map(parseInt); // [1, NaN, NaN]

parseInt 有一个可选的第二个参数 function parseInt(s, [radix=10]),但 map 调用 parseInt 带有三个参数:(element、index 和数组)。

我建议您将所需参数与可选/默认值参数分开。如果您的函数需要 1、2 或 3 个必需参数,而这些参数没有默认值,请将它们设为函数的位置参数,任何可选参数都应作为单个对象的命名属性跟随。如果您的函数需要 4 个或更多,那么通过单个对象参数的属性提供所有参数可能更有意义。

在您的情况下,我建议您像这样编写您的 deleteFile 函数:(edited per instead’s comments)…

// 不安全函数 read_file(fileName, deleteAfter=false) { if (deleteAfter) { console.log(读取然后删除 ${fileName}); } else { console.log(刚刚读取 ${fileName}); } } // 更好的函数 readFile(fileName, options) { const deleteAfter = !!(options && options.deleteAfter === true); read_file(fileName, deleteAfter); } console.log(‘不安全…’); [‘log1.txt’, ‘log2.txt’, ‘log3.txt’].map(read_file); console.log(‘更好…’); [‘log1.txt’, ‘log2.txt’, ‘log3.txt’].map(readFile);

运行上面的代码片段说明了潜伏在未使用参数的默认参数值背后的危险。

这个“更好的解决方案”是非常难以理解的。我宁愿建议检查像 typeof deleteAfter === 'bool' 这样的变量类型,否则抛出异常。另外,如果使用 map/foreach 等方法,请谨慎使用它们,并将调用的函数与匿名函数一起包装。 ['1', '2', '3'].map((value) => {read_file(value);})

那是个很好的观点。我试图避免在我的代码片段中使用库,但这个成语在纯 JavaScript 中非常混乱。就个人而言,我会使用 lodash 的 get 方法来检索 deleteAfter。如果 typeof 'deleteAfter' !== 'bool' 抛出异常也可能是一个很好的谨慎措施。我不喜欢设计要求调用者“谨慎使用”的方法。小心是函数的责任,而不是调用者的责任。最终行为应遵循最小意外原则。

我同意,该方法不应该这样写,调用它会破坏它的行为。但请记住,函数就像模型,调用者就像控制器。模型应该负责数据处理。函数(方法)应该期望数据,可以以错误的方式传递并处理它。这就是为什么检查参数类型加上抛出异常是最好的方法。尽管它更复杂。但它仍然可以让你免于挠头并继续问......为什么它不起作用?!然后......为什么它有效?!

答8:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

只需使用未定义的显式比较。

function read_file(file, delete_after)
{
    if(delete_after === undefined) { delete_after = false; }
}

答9:

huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

作为更新…使用 ECMAScript 6,您最终可以在函数参数声明中设置默认值,如下所示:

function f (x, y = 7, z = 42) {
  return x + y + z
}

f(1) === 50

由 - http://es6-features.org/#DefaultParameterValues 引用

这个答案没有用,因为它是重复的

答10:

huntsbot.com – 高效赚钱,自由工作

作为一个长期的C ++开发人员(Rookie to web development 😃),当我第一次遇到这种情况时,我在函数定义中进行了参数分配,就像问题中提到的那样,如下所示。

function myfunc(a,b=10)

但请注意,它不能在浏览器中一致地工作。对我来说,它适用于我桌面上的 chrome,但不适用于 android 上的 chrome。正如上面许多人提到的那样,更安全的选择是 -

    function myfunc(a,b)
    {
    if (typeof(b)==='undefined') b = 10;
......
    }

此答案的目的不是重复其他人已经提到的相同解决方案,而是告知函数定义中的参数分配可能适用于某些浏览器,但不要依赖它。

函数定义中的赋值在 IE 11 中也不起作用,这是适用于 Windows 8.1 的 IE 的最新版本。

如果有人想知道,function myfunc(a,b=10) 是 ES6 语法,其他答案中有指向兼容性表的链接。

答11:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

对于有兴趣让代码在 Microsoft Edge 中工作的任何人,请不要在函数参数中使用默认值。

function read_file(file, delete_after = false) {
    #code
}

在该示例中,Edge 将抛出错误“期望’)'”

为了解决这个问题

function read_file(file, delete_after) {
  if(delete_after == undefined)
  {
    delete_after = false;
  }
  #code
}

截至 2016 年 8 月 8 日,这仍然是一个问题

原文链接:https://www.huntsbot.com/qa/5DY0/set-a-default-parameter-value-for-a-javascript-function?lang=zh_CN&from=csdn

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值