Set a default parameter value for a JavaScript function
我希望一个javascript函数具有可选参数,我将其设置为默认值,如果未定义该值,则使用该参数(如果传递该值,则忽略该参数)。在Ruby中,您可以这样做:
1 2 3 | def read_file(file, delete_after = false) # code end |
这在javascript中有效吗?
1 2 3 | function read_file(file, delete_after = false) { // Code } |
从ES6/ES2015开始,默认参数在语言规范中。
1 2 3 | function read_file(file, delete_after = false) { // Code } |
只是工作。
参考:默认参数-MDN
Default function parameters allow formal parameters to be initialized with default values if no value or undefined is passed.
还可以通过销毁来模拟默认命名参数:
1 2 3 4 5 | // 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
有很多方法,但这是我的首选方法——它可以让你传递任何你想要的东西,包括假或空。(
1 2 3 4 5 | function foo(a, b) { a = typeof a !== 'undefined' ? a : 42; b = typeof b !== 'undefined' ? b : 'default_b'; ... } |
1 2 3 4 | function read_file(file, delete_after) { delete_after = delete_after ||"my default here"; //rest of code } |
它将
如果你想传递一个虚假的值,即
当处理一个函数的多个参数时,通常允许使用者传递对象中的参数参数,然后将这些值与包含函数默认值的对象合并是很有用的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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; }; |
使用
1 2 3 4 5 | // 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" }); |
我发现像这样简单的东西更简洁易读。
1 2 3 4 5 6 7 | function pick(arg, def) { return (typeof arg == 'undefined' ? def : arg); } function myFunc(x) { x = pick(x, 'my default'); } |
在EcmaScript 6中,您实际上能够准确地写下您拥有的内容:
1 2 3 | function read_file(file, delete_after = false) { // Code } |
如果不存在
有关更多信息,请参阅MDN文章。
默认参数值
使用ES6,您可以使用
1 2 3 4 5 6 7 8 9 | 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 |
这种模式是最常用的,但当我们传递如下值时是危险的
1 2 | foo(0, 42) foo( 0, 42 ); // 53 <-- Oops, not 42 |
为什么?因为
1 2 3 4 5 6 7 | 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 |
现在我们可以检查一个很好的有用语法,它是从
1 2 3 4 5 6 7 8 9 10 11 12 | 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` |
函数声明中的
默认值表达式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 |
如您所见,默认值表达式的计算比较缓慢,这意味着只有在需要时才运行它们——也就是说,当参数的参数被省略或未定义时。
默认值表达式甚至可以是内联函数表达式调用-通常称为立即调用的函数表达式
1 2 3 4 5 6 | function foo( x = (function(v){ return v + 11; })( 31 ) ) { console.log( x ); } foo(); // 42 |
该解决方案在JS中对我有效:
1 2 3 4 | function read_file(file, delete_after) { delete_after = delete_after || false; // Code } |
只需使用与未定义的显式比较。
1 2 3 4 | function read_file(file, delete_after) { if(delete_after === undefined) { delete_after = false; } } |
作为更新…使用ECMAScript 6,您可以在函数参数声明中最终设置默认值,如下所示:
1 2 3 4 5 | function f (x, y = 7, z = 42) { return x + y + z } f(1) === 50 |
如-http://es6 features.org/defaultParameterValues所引用
作为一个长时间的C++开发人员(新手到Web开发:),当我第一次遇到这种情况时,我做了函数定义中的参数赋值,就像它在下面提到的那样。
1 | function myfunc(a,b=10) |
但要注意,它不能在浏览器中始终如一地工作。对我来说,它可以在我的桌面上使用Chrome,但不能在Android上使用Chrome。更安全的选择,正如上面提到的那样-
1 2 3 4 5 | function myfunc(a,b) { if (typeof(b)==='undefined') b = 10; ...... } |
这个答案的目的不是重复其他人已经提到的相同的解决方案,而是通知函数定义中的参数分配可以在某些浏览器上工作,但不依赖于它。
我强烈建议在JavaScript中使用默认参数值时要格外小心。当与更高阶函数(如
1 | ['1', '2', '3'].map(parseInt); // [1, NaN, NaN] |
parseInt有一个可选的第二个参数
我建议您将所需参数从可选/默认值参数中分离出来。如果函数接受1、2或3个没有默认值意义的必需参数,则将它们作为函数的位置参数,任何可选参数都应作为单个对象的命名属性。如果函数取4个或更多,那么通过单个对象参数的属性提供所有参数可能更有意义。
在您的情况下,我建议您这样编写您的deletefile函数:(根据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // 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中使用There代码的人,不要在函数参数中使用默认值。
1 2 3 | function read_file(file, delete_after = false) { #code } |
在该示例中,边缘将引发一个错误"expecting")'"
为了避开这种使用
1 2 3 4 5 6 7 | function read_file(file, delete_after) { if(delete_after == undefined) { delete_after = false; } #code } |
截至2016年8月8日,这仍然是一个问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function helloWorld(name, symbol = '!!!') { name = name || 'worlds'; console.log('hello ' + name + symbol); } helloWorld(); // hello worlds!!! helloWorld('john'); // hello john!!! helloWorld('john', '(>.<)'); // hello john(>.<) helloWorld('john', undefined); // hello john!!! helloWorld(undefined, undefined); // hello worlds!!! |
如果要使用最新的
1 2 3 4 5 6 | function myFunction(someValue ="This is DEFAULT!") { console.log("someValue -->", someValue); } myFunction("Not A default value") // calling the function without default value myFunction() // calling the function with default value |
它叫
为了获得最大可能的兼容性,请使用:
1 2 3 4 5 6 7 | function myFunction(someValue) { someValue = (someValue === undefined) ?"This is DEFAULT!" : someValue; console.log("someValue -->", someValue); } myFunction("Not A default value") // calling the function without default value myFunction() // calling the function with default value |
这两个函数的行为与这些示例中的每一个都完全相同,这取决于这样一个事实:如果调用该函数时没有传递参数值,那么参数变量将是
ES6:正如大多数答案中已经提到的,在ES6中,您可以简单地初始化一个参数和一个值。
ES5:大多数给出的答案对我来说都不够好,因为在某些情况下,我可能不得不向函数传递错误的值,如
1 2 3 4 | function foo (param1, param2) { param1 = arguments.length >= 1 ? param1 :"default1"; param2 = arguments.length >= 2 ? param2 :"default2"; } |
按照语法
1 2 3 | function [name]([param1[ = defaultValue1 ][, ..., paramN[ = defaultValueN ]]]) { statements } |
可以定义形式参数的默认值。并使用typeof函数检查未定义的值。
1 2 3 4 5 6 | function throwIfNoValue() { throw new Error('Missing argument'); } function foo(argValue = throwIfNoValue()) { return argValue ; } |
这里foo()是一个函数,它有一个名为argValue的参数。如果在这里不传递函数调用中的任何内容,那么将调用函数throwifnovalue(),并将返回的结果赋给唯一的参数argValue。这就是如何将函数调用用作默认参数的方法。这使得代码更加简单易读。
此示例取自此处
如果您使用的是
1 2 3 4 5 | function test (foo = 1, bar = 2) { console.log(foo, bar); } test(5); // foo gets overwritten, bar remains default parameter |
如果需要
1 2 3 4 5 6 7 8 | function test(foo, bar) { foo = foo || 2; bar = bar || 0; console.log(foo, bar); } test(5); // foo gets overwritten, bar remains default parameter |
在上述语法中,使用
是的,ES6完全支持使用默认参数:
1 2 3 | function read_file(file, delete_after = false) { // Code } |
或
1 2 3 | const read_file = (file, delete_after = false) => { // Code } |
但在ES5之前,您可以轻松做到:
1 2 3 4 | function read_file(file, delete_after) { var df = delete_after || false; // Code } |
也就是说,如果有这个值,就使用这个值,否则,就使用
注:如果将一个值传递给es6-one,即使该值不稳定,也会被新值替换,如
如果出于某种原因,您不在ES6上并且正在使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var fn = function(a, b) { a = _.defaultTo(a, 'Hi') b = _.defaultTo(b, 'Mom!') console.log(a, b) } fn() // Hi Mom! fn(undefined, null) // Hi Mom! fn(NaN, NaN) // Hi Mom! fn(1) // 1"Mom!" fn(null, 2) // Hi 2 fn(false, false) // false false fn(0, 2) // 0 2 |
1 | <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"> |
如果当前值为NaN、null或Undefined,则设置默认值。
1 2 3 | def read_file(file, delete_after = false) # code end |
以下代码可能在这种情况下工作,包括ECMAScript 6(ES6)和早期版本。
1 2 3 4 5 6 7 8 | function read_file(file, delete_after) { if(delete_after == undefined) delete_after = false;//default value console.log('delete_after =',delete_after); } read_file('text1.txt',true); read_file('text2.txt'); |
当调用时跳过函数的参数值时,语言中的默认值起作用,在javascript中,它被分配给未定义的。这种方法在编程上看起来不具有吸引力,但具有向后兼容性。
是的,这被称为默认参数
如果没有传递值或未定义,则默认函数参数允许用默认值初始化形参。
Syntax:
1 2 3 | function [name]([param1[ = defaultValue1 ][, ..., paramN[ = defaultValueN ]]]) { statements } |
描述:
函数的参数默认为未定义,但是,在某些情况下,设置不同的默认值可能很有用。这是默认参数可以帮助的地方。
在过去,设置默认值的一般策略是测试函数体中的参数值,如果参数值未定义,则赋值。如果调用中没有提供值,则其值将未定义。您必须设置条件检查以确保参数未定义
使用ES2015中的默认参数,不再需要签入函数体。现在您可以简单地在函数头中放置一个默认值。
差异示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // OLD METHOD function multiply(a, b) { b = (typeof b !== 'undefined') ? b : 1; return a * b; } multiply(5, 2); // 10 multiply(5, 1); // 5 multiply(5); // 5 // NEW METHOD function multiply(a, b = 1) { return a * b; } multiply(5, 2); // 10 multiply(5, 1); // 5 multiply(5); // 5 |
不同的语法示例:
填充未定义的值与其他错误值:
即使在调用时显式设置了该值,num参数的值也是默认值。
1 2 3 4 5 6 7 8 9 10 | function test(num = 1) { console.log(typeof num); } test(); // 'number' (num is set to 1) test(undefined); // 'number' (num is set to 1 too) // test with other falsy values: test(''); // 'string' (num is set to '') test(null); // 'object' (num is set to null) |
在调用时评估:
默认参数在调用时进行计算,因此与其他一些语言不同,每次调用函数时都会创建一个新对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | function append(value, array = []) { array.push(value); return array; } append(1); //[1] append(2); //[2], not [1, 2] // This even applies to functions and variables function callSomething(thing = something()) { return thing; } function something() { return 'sth'; } callSomething(); //sth |
默认参数可用于以后的默认参数:
已遇到的参数可用于以后的默认参数
1 2 3 4 5 6 7 8 9 10 11 12 13 | function singularAutoPlural(singular, plural = singular + 's', rallyingCry = plural + ' ATTACK!!!') { return [singular, plural, rallyingCry]; } //["Gecko","Geckos","Geckos ATTACK!!!"] singularAutoPlural('Gecko'); //["Fox","Foxes","Foxes ATTACK!!!"] singularAutoPlural('Fox', 'Foxes'); //["Deer","Deer","Deer ... change."] singularAutoPlural('Deer', 'Deer', 'Deer peaceably and respectfully \ petition the government for positive change.') |
函数体内部定义的函数:
Gecko 33(火狐33/Thunderbird 33/Seamonkey 2.30)中介绍。在函数体中声明的函数不能在默认参数内引用并引发引用错误(当前在spidermonkey中为typeerror,请参阅bug 1022967)。默认参数总是先执行,函数体内部的函数声明随后计算。
1 2 3 4 | // Doesn't work! Throws ReferenceError. function f(a = go()) { function go() { return ':P'; } } |
默认参数后没有默认值的参数:
在gecko 26(firefox 26/thunderbird 26/seamonkey 2.23/firefox os 1.2)之前,以下代码导致了语法错误。这已在bug 777060中修复,并在以后的版本中按预期工作。参数仍然设置为从左到右,覆盖默认参数,即使以后有没有默认值的参数。
1 2 3 4 5 6 | function f(x = 1, y) { return [x, y]; } f(); // [1, undefined] f(2); // [2, undefined] |
具有默认值分配的已破坏参数:
可以使用带有析构函数赋值符号的默认值赋值
1 2 3 4 5 | function f([x, y] = [1, 2], {z: z} = {z: 3}) { return x + y + z; } f(); // 6 |
是的,这将在JavaScript中工作。您也可以这样做:
1 2 3 4 5 6 7 8 9 10 | function func(a=10,b=20) { alert (a+' and '+b); } func(); // Result: 10 and 20 func(12); // Result: 12 and 20 func(22,25); // Result: 22 and 25 |