为JavaScript函数设置默认参数值

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

def read_file(file, delete_after = false)# codeend

这在JavaScript中工作吗?

function read_file(file, delete_after = false) {// Code}
1416873 次浏览
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对语言的调查,请查看关于运算符的部分

如果您想传入Falsey值,即falsenullundefined0"",则此方法不起作用。如果您需要传入Falsey值,则需要使用Tom Ritter的回答中的方法。

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

function read_file(values) {values = merge({delete_after : "my default here"}, values || {});
// rest of code}
// simple implementation based on $.extend() from jQueryfunction 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 valueread_file({ file: "my file" });
// will override default delete_after valueread_file({ file: "my file", delete_after: "my value" });

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

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

只是工作。

参考:默认参数-MDN

如果传递了没有价值未定义,则默认函数参数允许使用默认值初始化形式参数。

在ES6中,您可以通过解构模拟默认的命名参数

// the `= {}` below lets you call the function without any parametersfunction myFor({ start = 5, end = 1, step = -1 } = {}) { // (A)// Use the variables `start`, `end` and `step` here···}
// sample call using an objectmyFor({ start: 3, end: 0 });
// also OKmyFor();myFor({});

前ES2015

有很多方法,但这是我的首选方法-它允许您传入任何您想要的内容,包括false或null。

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

我发现像这样简单的东西更简洁,更具个人可读性。

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_afterfalseundefined。您可以使用ES6功能,例如巴别塔的转译器。

有关更多信息,请参阅MDN文章

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

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

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

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

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

这个解决方案在js中为我工作:

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

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

function myfunc(a,b=10)

但请注意,它不能在浏览器上一致工作。对我来说,它在我的桌面上的chrome上工作,但在android上的chrome上不起作用。更安全的选择,正如上面提到的-

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

这个答案的意图不是重复相同的解决方案,其他人已经提到了,而是通知函数定义中的参数分配可能在某些浏览器上工作,但不要依赖它。

是的,这将在Javascript中工作。你也可以这样做:

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

对于任何有兴趣让代码在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日,这仍然是一个问题

默认参数值

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

function foo(x,y) {x = x || 11;y = y || 31;console.log( x + y );}foo(); // 42foo( 5, 6 ); // 11foo( 5 ); // 36foo( 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 ); // 42foo( undefined, 6 ); // 17

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

function foo(x = 11, y = 31) {console.log( x + y );}
foo(); // 42foo( 5, 6 ); // 11foo( 0, 42 ); // 42foo( 5 ); // 36foo( 5, undefined ); // 36 <-- `undefined` is missingfoo( 5, null ); // 5 <-- null coerces to `0`foo( undefined, 6 ); // 17 <-- `undefined` is missingfoo( 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 13foo( 10 ); // "bar called"// 10 15y = 6;foo( undefined, 10 ); // 9 10

如您所见,默认值表达式是延迟计算的,这意味着它们仅在需要时运行-也就是说,当参数的参数被省略或未定义时。

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

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

根据语法

function [name]([param1[ = defaultValue1 ][, ..., paramN[ = defaultValueN ]]]) {statements}

您可以定义形式参数的默认值。并使用typeof函数检查未定义的值。

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

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

parseInt有一个可选的第二个参数function parseInt(s, [基数=10]),但map调用parseInt有三个参数:(元素索引阵列)。

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

在您的情况下,我建议您像这样编写deleteFile函数:(按需编辑instead评论数)…

// unsafefunction read_file(fileName, deleteAfter=false) {if (deleteAfter) {console.log(`Reading and then deleting ${fileName}`);} else {console.log(`Just reading ${fileName}`);}}
// betterfunction 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);

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

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!!!

function throwIfNoValue() {throw new Error('Missing argument');}function foo(argValue = throwIfNoValue()) {return argValue ;}

这里foo()是一个函数,它有一个名为artValue的参数。如果我们在这里的函数调用中没有传递任何东西,那么函数throwIfNoValue()将被调用,返回的结果将被分配给唯一的参数artValue。这就是函数调用可以用作默认参数的方式。这使得代码更加简化和可读性。

这个例子是从这里开始的

如果您想使用最新的#0语法,请使用此选项:

function myFunction(someValue = "This is DEFAULT!") {console.log("someValue --> ", someValue);}
myFunction("Not A default value") // calling the function without default valuemyFunction()  // calling the function with default value

它被称为#0。如果没有传递值或未定义,它允许使用默认值初始化形式参数。注意:它不适用于Internet Explorer或较旧的浏览器。

对于最大可能的兼容性使用:

function myFunction(someValue) {someValue = (someValue === undefined) ? "This is DEFAULT!" : someValue;console.log("someValue --> ", someValue);}
myFunction("Not A default value") // calling the function without default valuemyFunction()  // calling the function with default value

这两个函数具有完全相同的行为,因为这些示例中的每一个都依赖于这样一个事实,即如果在调用该函数时没有传递参数值,则参数变量将为undefined

如果您使用的是ES6+,您可以通过以下方式设置默认参数:

function test (foo = 1, bar = 2) {console.log(foo, bar);}
test(5); // foo gets overwritten, bar remains default parameter

如果您需要ES5语法,您可以通过以下方式完成:

function test(foo, bar) {foo = foo || 2;bar = bar || 0;  
console.log(foo, bar);}
test(5); // foo gets overwritten, bar remains default parameter

在上面的语法中使用了OR运算符。如果this可以转换为true,如果不能,则OR运算符始终返回第一个值。当没有相应参数调用函数时,JS引擎将参数变量(在我们的示例中为bar)设置为undefinedundefined然后转换为false,因此OR运算符返回值0。

ES6:正如大多数答案中已经提到的,在ES6中,您可以简单地初始化一个参数和一个值。


ES5:大多数给定的答案对我来说都不够好,因为有时我可能不得不将0nullundefined等假值传递给函数。为了确定参数是否未定义,因为这是我传递的值,而不是未定义的,因为根本没有定义,我这样做:

function foo (param1, param2) {param1 = arguments.length >= 1 ? param1 : "default1";param2 = arguments.length >= 2 ? param2 : "default2";}
def read_file(file, delete_after = false)# codeend

以下代码可能在这种情况下工作,包括ECMAScript 6(ES6)以及早期版本。

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中它被分配给未定义。这种方法在编程上看起来没有吸引力,但有向后兼容性

是的,这被称为默认参数

默认函数参数允许形式参数在没有传递值或未定义时使用默认值进行初始化。

语法:

function [name]([param1[ = defaultValue1 ][, ..., paramN[ = defaultValueN ]]]) {statements}

问题描述

函数的参数默认为未定义但是,在某些情况下,设置不同的默认值可能会很有用。这就是默认参数可以提供帮助的地方。

过去,设置默认值的一般策略是在函数体中测试参数值,如果它们未定义则赋值。如果调用中未提供任何值,则其值将为未定义。您必须设置条件检查以确保参数不是未定义的

使用ES2015中的默认参数,不再需要在函数体中进行检查。现在您可以简单地在函数头中放置默认值。

差异示例:

// OLD METHODfunction multiply(a, b) {b = (typeof b !== 'undefined') ?  b : 1;return a * b;}
multiply(5, 2); // 10multiply(5, 1); // 5multiply(5);    // 5

// NEW METHODfunction multiply(a, b = 1) {return a * b;}
multiply(5, 2); // 10multiply(5, 1); // 5multiply(5);    // 5

不同的语法示例:

填充未定义与其他false sy值:

即使在调用时显式设置了该值,num参数的值也是默认值。

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)

在通话时评估:

默认参数在调用时被评估,因此与其他一些语言不同,每次调用函数时都会创建一个新对象。

function append(value, array = []) {array.push(value);return array;}
append(1); //[1]append(2); //[2], not [1, 2]

// This even applies to functions and variablesfunction callSomething(thing = something()) {return thing;}
function something() {return 'sth';}
callSomething();  //sth

默认参数可用于以后的默认参数:

已经遇到的参数可用于以后的默认参数

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(Firefox 33/Thunderbird 33/SeaMonkey 2.30)中引入。在函数体中声明的函数不能在默认参数中引用并抛出引用错误(目前SpiderMonkey中的TypeError,请参阅bug1022967)。默认参数始终首先执行,然后再评估函数体中的函数声明。

// 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)之前,以下代码导致了一个语法错误。这已在bug777060中修复,并在以后的版本中按预期工作。参数仍然从左到右设置,覆盖默认参数,即使后来有没有默认值的参数。

function f(x = 1, y) {return [x, y];}
f(); // [1, undefined]f(2); // [2, undefined]

带有默认值赋值的非结构化参数:

您可以将默认值赋值与解构赋值符号一起使用

function f([x, y] = [1, 2], {z: z} = {z: 3}) {return x + y + z;}
f(); // 6

如果由于某种原因,您在ES6上排名第2,而在使用#0时排名第3,这里有一种通过#1方法默认函数参数的简洁方法:

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 2fn(false, false)     // false falsefn(0, 2)             // 0 2
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Which will set the default if the current value is NaN, null, or undefined

是的,ES6完全支持使用默认参数:

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

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

但是在ES5之前,你可以很容易地做到这一点:

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

这意味着如果值在那里,使用该值,否则,使用||操作后的第二个值,它做同样的事情…

备注:也有一个很大的区别,如果你传递一个值ES6一个值是false sy,这将被替换为新值,像null""……但ES5一个只有在传递的值是true的情况下才会被替换,那是因为||的工作方式……

设置默认参数的另一种方法是使用参数的对象映射,而不是直接使用参数。例如,

const defaultConfig = {category: 'Animals',legs: 4};
function checkOrganism(props) {const category = props.category || defaultConfig.category;const legs = props.legs || defaultConfig.legs;}

这样,很容易扩展参数,而不用担心参数长度不匹配。

答案是肯定的。事实上,有很多语言都支持默认参数。Python就是其中之一:

def(a, enter="Hello"):print(a+enter)

尽管由于括号,这是Python 3代码,但函数中的默认参数也适用于JS。

例如,在您的案例中:

function read_file(file, deleteAfter=false){console.log(deleteAfter);}
read_file("test.txt");

但有时你真的不需要默认参数。

您可以在函数开始后立即定义变量,如下所示:

function read_file(file){var deleteAfter = false;console.log(deleteAfter);}
read_file("test.txt");

在我的两个示例中,它返回相同的内容。但有时它们实际上可能很有用,例如在非常高级的项目中。

所以,总而言之,默认参数值可以在JS中使用。但这与在函数开始后定义变量几乎是一回事。然而,有时它们仍然非常有用。正如你可能注意到的,默认参数值比在函数开始后定义参数的标准方法少1行代码。

编辑:这非常重要!这将没有在IE中工作。参见留档。因此,对于IE,您必须使用“在函数顶部定义变量”方法。默认参数在IE中不起作用。

未来之声

将来,您将能够将一个对象“传播”到另一个对象(目前截至2019年Edge不支持!)-演示如何将其用于漂亮的默认选项,无论顺序如何:

function test(options) {var options = {// defaultsurl: 'defaultURL',some: 'somethingDefault',// override with input options...options};    
var body = document.getElementsByTagName('body')[0];body.innerHTML += '<br>' + options.url + ' : ' + options.some;}test();test({});test({url:'myURL'});test({some:'somethingOfMine'});test({url:'overrideURL', some:'andSomething'});test({url:'overrideURL', some:'andSomething', extra:'noProblem'});

MDN参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

…同时Edge DOES支持Object.assign()(IE没有,但我真的希望我们能把IE抛在脑后:))

你也可以这样做

    function test(options) {var options = Object.assign({// defaultsurl: 'defaultURL',some: 'somethingDefault',}, options); // override with input options        
var body = document.getElementsByTagName('body')[0];body.innerHTML += '<br>' + options.url + ' : ' + options.some;}test();test({});test({url:'myURL'});test({some:'somethingOfMine'});test({url:'overrideURL', some:'andSomething'});test({url:'overrideURL', some:'andSomething', extra:'noProblem'});

编辑:由于对const选项的评论-在函数的其余部分使用常量选项的问题实际上是没有,你不能这样做,只是你不能在自己的声明中使用常量变量-你必须将输入命名调整为

function test(input_options){const options = {// defaultssomeKey:    'someDefaultValue',anotherKey: 'anotherDefaultValue',
// merge-in input options...input_options};
// from now on use options with no problem}

只是为了展示我的技能(lol),上面的函数甚至可以在没有命名参数的情况下编写,如下所示:

ES5及以上

function foo() {a = typeof arguments[0] !== 'undefined' ? a : 42;b = typeof arguments[1] !== 'undefined' ? b : 'default_b';...}

ES6及以上

function foo(...rest) {a = typeof rest[0] !== 'undefined' ? a : 42;b = typeof rest[1] !== 'undefined' ? b : 'default_b';...}

是-证明:

function read_file(file, delete_after = false) {// Codeconsole.log({file,delete_after});}


// TESTread_file("A");read_file("B",true);read_file("C",false);

我注意到一些回答提到使用默认参数不能移植到其他浏览器,但公平地指出,您可以使用像Babel这样的转译器将代码转换为ES5语法,用于对现代JS功能支持有限的浏览器。

所以这个:

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

将被转译为这样(在Babel REPL中尝试->https://babeljs.io/repl/):

"use strict";
function read_file(file) {
var delete_after =arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;  
//Code...
}

当然,如果你不打算使用转译,那么在函数体中设置默认参数就像其他人演示的那样也是完全可以的。

export const getfilesize = (bytes, decimals = 2) => {if (bytes === 0){return '0 Bytes';}else{const k = 1024;const dm = decimals < 0 ? 0 : decimals;const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];const i = Math.floor(Math.log(bytes) / Math.log(k));return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}}