我想要一个JavaScript函数可以有可选参数,并且可以设置默认值,如果该值未定义则使用默认值(如果传递了值,则忽略默认值)。在Ruby中,您可以这样做:
def read_file(file, delete_after = false)
# code
end
这个JavaScript代码可以运行吗?
function read_file(file, delete_after = false) {
// Code
}
我想要一个JavaScript函数可以有可选参数,并且可以设置默认值,如果该值未定义则使用默认值(如果传递了值,则忽略默认值)。在Ruby中,您可以这样做:
def read_file(file, delete_after = false)
# code
end
这个JavaScript代码可以运行吗?
function read_file(file, delete_after = false) {
// Code
}
从ES6/ES2015开始, 默认参数已经在语言规范中了。
function read_file(file, delete_after = false) {
// Code
}
只需运行。
参考:默认参数 - MDN
如果没有传递值或未定义,则默认函数参数允许使用默认值初始化形式参数。
在ES6中,您可以通过解构模拟默认的命名参数:
// 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);
- Camilo Martintypeof
就是多余的。function foo(data) { var bar = data.bar !== undefined ? data.bar : 'default'; }
这样不会抛出引用错误并且简洁明了。 - Dziamida = a
和b = b
。而且,那个带有复杂条件的三元运算符可能会让未来的维护者难以阅读。我更喜欢以下语法:
if (typeof a == 'undefined') a = 42
typeof
有什么原因吗?直接使用 a === undefined
似乎更简单。而且这样做,如果拼错了 undefined
,你会得到一个引用错误(reference error)。 - Abe Voelkerfunction read_file(file, delete_after) {
delete_after = delete_after || "my default here";
//rest of code
}
这段代码给delete_after
赋值。如果它不是falsey的值,则将其赋值为delete_after
的值,否则将其赋值为字符串"my default here"
。如需更多详细信息,请查看Doug Crockford对该语言的调查,并查看运算符部分。false
、null
、undefined
、0
或""
,则此方法无效。如果需要传递falsey值,则需要使用Tom Ritter解答中的方法。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" });
delete_after
没有得到表达式 delete_after || "my default value"
的布尔结果呢? - Ayush个人认为像这样简单的写法更加简洁易读。
function pick(arg, def) {
return (typeof arg == 'undefined' ? def : arg);
}
function myFunc(x) {
x = pick(x, 'my default');
}
_.defaults(iceCream, {flavor: "vanilla", sprinkles: "lots"});
。按照这个答案中所显示的方式使用全局命名空间被许多人认为是一种不好的做法。如果你不想使用 underscore,你也可以考虑自己编写此常见任务的实用程序(例如 util.default(arg, "defaul value")
),但我大多数情况下最终还是会使用 underscore,没必要重复造轮子。 - andersandundefined
,导致测试失败。 - Alnitak在ECMAScript 6中,你实际上可以像你所写的那样编写:
function read_file(file, delete_after = false) {
// Code
}
如果delete_after
未定义或不存在,这将将其设置为false
。 您可以使用ES6功能,例如Babel进行转译。
默认参数值
在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为假
,所以x || 11结果是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
中添加的,它可以简化给缺失参数设置默认值的赋值过程:
现在,我们可以检查一种很有帮助的语法,这是在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
默认值表达式
函数
默认值不仅可以是简单的值,如31;它们可以是任何有效的表达式,甚至是函数调用
:
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
这个解决方案对我在js中起作用:
function read_file(file, delete_after) {
delete_after = delete_after || false;
// Code
}
在JavaScript中使用默认参数值时,我强烈建议谨慎使用。当与诸如forEach、map和reduce等高阶函数一起使用时,它经常会导致错误。例如,请考虑以下代码行:
['1', '2', '3'].map(parseInt); // [1, NaN, NaN]
parseInt有一个可选的第二个参数function parseInt(s, [
radix=10])
,但是map调用parseInt
时会传递三个参数:(element, index和array)。
我建议您将必需的参数与可选/默认值参数分开。如果您的函数需要1、2或3个必需参数,而没有任何默认值是有意义的,则应将它们作为函数的位置参数,任何可选参数都应作为单个对象的命名属性跟随其后。如果您的函数需要4个或更多个参数,也许通过单个对象参数的属性提供所有参数更有意义。
在您的情况下,我建议您这样编写您的deleteFile函数:(根据instead
的评论编辑)...
// unsafe
function read_file(fileName, deleteAfter=false) {
if (deleteAfter) {
console.log(`Reading and then deleting ${fileName}`);
} else {
console.log(`Just reading ${fileName}`);
}
}
// better
function readFile(fileName, options) {
const deleteAfter = !!(options && options.deleteAfter === true);
read_file(fileName, deleteAfter);
}
console.log('unsafe...');
['log1.txt', 'log2.txt', 'log3.txt'].map(read_file);
console.log('better...');
['log1.txt', 'log2.txt', 'log3.txt'].map(readFile);
运行上述片段展示了默认参数值对未使用参数的危险潜伏。
typeof deleteAfter === 'bool'
,如果类型不符则抛出异常。此外,在使用 map/foreach 等方法时,请小心使用,并将被调用的函数包装在匿名函数中。例如:['1', '2', '3'].map((value) => {read_file(value);})
- insteadget
方法来检索deleteAfter。如果typeof 'deleteAfter' !== 'bool'
,抛出异常也可能是一个很好的谨慎措施。我不喜欢设计需要调用者“小心使用”的方法。小心使用是函数的责任,而不是调用者的责任。最终行为应该遵循最少惊讶原则。 - Doug Coburn只需使用一个明确的与 undefined 的比较。
function read_file(file, delete_after)
{
if(delete_after === undefined) { delete_after = false; }
}
更新一下,使用ECMAScript 6,你终于可以像这样在函数参数声明中设置默认值:FINALLY
function f (x, y = 7, z = 42) {
return x + y + z
}
f(1) === 50
作为一个长期从事C++开发的人(从新手到Web开发 :)),当我第一次遇到这种情况时,我按照问题中所提到的方式在函数定义中进行了参数赋值,如下所示。
function myfunc(a,b=10)
但要注意,它在不同浏览器上的表现并不一致。对我来说,在我的台式机上使用chrome可以正常工作,但在安卓手机上的chrome上无法正常工作。 更为安全的选择,就像上面很多人提到的那样是 -
function myfunc(a,b)
{
if (typeof(b)==='undefined') b = 10;
......
}
本回答的意图不是重复其他人已经提到的相同解决方案,而是要通知您函数定义中的参数赋值可能在某些浏览器上有效,但请不要依赖于它。
function myfunc(a,b=10)
是 ES6 语法,其他答案中有兼容性表的链接。 - gcampbell
ES6
开始,这将起作用:function read_file(file, delete_after=false){};
。 - Azhar Uddin Sheikh