我希望JavaScript函数具有可选参数,我将其设置为默认值,如果未定义该值,则使用该参数.在Ruby中你可以这样做:
def read_file(file, delete_after = false) # code end
这是否适用于JavaScript?
function read_file(file, delete_after = false) { // Code }
Tom Ritter.. 3210
从ES6/ES2015开始,默认参数在语言规范中.
function read_file(file, delete_after = false) { // Code }
只是工作.
参考:默认参数 - MDN
如果没有传递值或未定义,则默认函数参数允许使用默认值初始化形式参数.
您还可以通过解构来模拟默认命名参数:
// 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 ··· }
预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);` (207认同)
有没有理由使用`typeof`?做一个'= = undefined'似乎更简单.另外,如果拼错了`undefined`而不是把它放在一个字符串中,那么你会得到一个引用错误. (9认同)
我知道它确实很小,但我不喜欢当这些参数未定义时你如何分配`a = a`和`b = b`.此外,具有复杂条件的三元运算符可能难以为将来的维护者阅读.我更喜欢以下语法:`if(typeof a =='undefined')a = 42` - 没有不必要的赋值加上更容易阅读. (8认同)
如果你检查一个对象的属性,那么`typeof`是多余的.`function foo(data){var bar = data.bar!== undefined?data.bar:'default'; 这不会引发参考错误,而且简洁. (7认同)
@SiPlus并且在尝试使用`undefined`对象时免费获得额外的参考错误:p即使它可能适用于某些浏览器并且可能更快,`null`仍然是一个对象而`undefined`是对原语的引用试图告诉这里什么都没有的类型,甚至不是`null`.简而言之,请参见此处的两种情况:[JavaScript/Reference/Global_Objects/undefined](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/undefined). (5认同)
这不适合我.如果没有传入任何值,则无法在参数上使用typeof.你必须使用`var === undefined` (3认同)
@AbeVoelker在旧的javascript引擎中,'undefined`不是关键字存在一些问题 - 所以你可以覆盖它.你总是可以使用`void`生成一个undefined - 例如:`a = a!== void 0?a:"默认";` - 它很难看,而且代码覆盖undefined仍有根本错误. (3认同)
@SiPlus然后它不是**不再是默认值除了快速改变传递给函数的很多值(_like使用定义的常量代替`null`_)之外没有任何意义.基本上你的代码_translates_`null`到'42`.如果在你的例子中`a`是'undefined`那么它将_stay_`undefined`并且它没有获得任何默认值. (2认同)
为什么不简单地使用不那么神秘的`if(typeof a ==='undefined')a = 42;`? (2认同)
Russ Cam.. 590
function read_file(file, delete_after) { delete_after = delete_after || "my default here"; //rest of code }
这将delete_after
赋值为delete_after
if if不是falsey值,否则分配字符串"my default here"
.有关更多详细信息,请查看Doug Crockford对该语言的调查,并查看操作员部分.
如果你想在一个通过这种方法行不通falsey值即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" });
我发现这个不足,因为我可能想要传递虚假. (112认同)
我觉得它适合大多数情况 (52认同)
因为它不适用于虚假值,它可能会造成维护噩梦.一些代码总是在之前通过了真正的值并突然失败,因为在可以使用更强大的方法的情况下应该避免传递假的. (49认同)
或者,你可能只是默认为一个假值 - 这通常是一个很好的默认值(例如,bools为false,字符串为空字符串,0为数字等) - 在这种情况下,它并不重要传入 (2认同)
tj111.. 144
我发现像这样简单的东西更加简洁和个性化.
function pick(arg, def) { return (typeof arg == 'undefined' ? def : arg); } function myFunc(x) { x = pick(x, 'my default'); }
更新:如果你正在使用**underscore.js**我发现使用`_.defaults(iceCream,{flavor:"vanilla",splash:"lots"})更好!`.许多人认为使用这个答案中显示的全局命名空间是一种不好的做法.您也可以考虑为这个常见任务滚动自己的实用程序(例如``util.default(arg,"defaul value")`)如果不想使用下划线,但我最终迟早会使用下划线,无论如何不重点发明轮子. (6认同)
@OsamaBinLogin你说的对于当前的JS是正确的 - 旧的测试仍然存在,因为在某些浏览器上它曾经可能用一些其他值覆盖`undefined`,导致测试失败. (3认同)
我实际推荐这个,我用它并称之为"por",代表"参数或" (2认同)
不要说typeof arg =='undefined',而是说arg === undefined (2认同)
@Alnitak:仍然可以覆盖`undefined`.因此,使用`typeof`和`'undefined'`仍然是个好主意. (2认同)
Felix Kling.. 62
在ECMAScript 6中,您实际上可以准确地写出您拥有的内容:
function read_file(file, delete_after = false) { // Code }
这将设置delete_after
为false
不存在或undefined
.今天你可以使用像这样的ES6功能,如Babel等转发器.
有关更多信息,请参阅MDN文章.
从ES6/ES2015开始,默认参数在语言规范中.
function read_file(file, delete_after = false) { // Code }
只是工作.
参考:默认参数 - MDN
如果没有传递值或未定义,则默认函数参数允许使用默认值初始化形式参数.
您还可以通过解构来模拟默认命名参数:
// 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 ··· }
预ES2015,
有很多方法,但这是我首选的方法 - 它允许你传递任何你想要的东西,包括false或null.(typeof null == "object"
)
function foo(a, b) { a = typeof a !== 'undefined' ? a : 42; b = typeof b !== 'undefined' ? b : 'default_b'; ... }
function read_file(file, delete_after) { delete_after = delete_after || "my default here"; //rest of code }
这将delete_after
赋值为delete_after
if if不是falsey值,否则分配字符串"my default here"
.有关更多详细信息,请查看Doug Crockford对该语言的调查,并查看操作员部分.
如果你想在一个通过这种方法行不通falsey值即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" });
我发现像这样简单的东西更加简洁和个性化.
function pick(arg, def) { return (typeof arg == 'undefined' ? def : arg); } function myFunc(x) { x = pick(x, 'my default'); }
在ECMAScript 6中,您实际上可以准确地写出您拥有的内容:
function read_file(file, delete_after = false) { // Code }
这将设置delete_after
为false
不存在或undefined
.今天你可以使用像这样的ES6功能,如Babel等转发器.
有关更多信息,请参阅MDN文章.
默认参数值
使用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
该解决方案适用于js:
function read_file(file, delete_after) { delete_after = delete_after || false; // Code }
只需使用与undefined的显式比较.
function read_file(file, delete_after) { if(delete_after === undefined) { delete_after = false; } }
作为更新...使用ECMAScript 6,您可以在函数参数声明中最终设置默认值,如下所示:
function f (x, y = 7, z = 42) { return x + y + z } f(1) === 50
正如 - http://es6-features.org/#DefaultParameterValues所引用的那样
作为一个长期的C++开发人员(Rookie to web development :)),当我第一次遇到这种情况时,我在函数定义中进行了参数赋值,就像在问题中提到的那样,如下所示.
function myfunc(a,b=10)
但请注意,它不能跨浏览器一致地工作.对我来说,它在我的桌面上使用chrome,但在android上没有使用chrome.如上所述,更安全的选择是 -
function myfunc(a,b) { if (typeof(b)==='undefined') b = 10; ...... }
对这个答案的意图不是重复相同的解决方案,其他人已经提到过,但是要告知函数定义中的参数赋值可能适用于某些浏览器,但不依赖于它.
在javascript中使用默认参数值时,我强烈建议极其谨慎.与高阶函数等结合使用时,它常常会造成错误forEach
,map
和reduce
.例如,考虑以下代码行:
['1', '2', '3'].map(parseInt); // [1, NaN, NaN]
parseInt有一个可选的第二个参数function parseInt(s, [
radix=10])
但是parseInt
有三个参数的map调用:(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);
对于有兴趣在Microsoft Edge中使用代码工作的任何人,请不要在函数参数中使用默认值.
function read_file(file, delete_after = false) { #code }
在该示例中,Edge将抛出错误"Expecting")'"
绕过这个用途
function read_file(file, delete_after) { if(delete_after == undefined) { delete_after = false; } #code }
截至2016年8月8日,这仍然是一个问题