设置 JavaScript 函数的默认参数值

I would like a JavaScript function to have optional arguments which I set a default on, which gets used if the value isn't defined. In Ruby you can do it like this:

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

Does this work in JavaScript?

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

转载于:https://stackoverflow.com/questions/894860/set-a-default-parameter-value-for-a-javascript-function

21个回答

From ES6/ES2015, default parameters is in the language specification.

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

just works.

Reference: Default Parameters - MDN

Default function parameters allow formal parameters to be initialized with default values if no value or undefined is passed.

You can also 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
    ···
}

Pre ES2015,

There are a lot of ways, but this is my preferred method - it lets you pass in anything you want, including false or null. (typeof null == "object")

function foo(a, b) {
  a = typeof a !== 'undefined' ? a : 42;
  b = typeof b !== 'undefined' ? b : 'default_b';
  ...
}
csdnceshi73
喵-见缝插针 You can also use default value assignment with the destructuring assignment notation
2 年多之前 回复
csdnceshi65
larry*wei According to this, default parameters are now supported by most browsers (including mobile), IE being the exception: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… and kangax.github.io/compat-table/es6
大约 3 年之前 回复
csdnceshi66
必承其重 | 欲带皇冠 I suggest updating your answer to warn about the gotchas with using default parameter values. See my post below: stackoverflow.com/questions/894860/…
大约 3 年之前 回复
csdnceshi63
elliott.david Do you have to pass an input for the 2nd parameter or can it be left out?
3 年多之前 回复
csdnceshi75
衫裤跑路 Is there a reason why you don't use a positive if? a = typeof a === 'undefined' ? 42 : a; I mean === instead of !== ?
3 年多之前 回复
csdnceshi72
谁还没个明天 You can simply write function foo(a, b) { a = a || 42; b = b || 'default_b'; ... }
接近 4 年之前 回复
csdnceshi64
游.程 Note that setting defaults in the parameter declaration doesn't currently work in mobile Safari or Chrome.
大约 4 年之前 回复
weixin_41568110
七度&光 FYI: MS Edge and IE11 throw an error when assigning a default value like so: function badArg(imOK, imNOT='') {} - it will balk at the ='' - didn't test null, just removed it because it wasn't actually necessary.
大约 4 年之前 回复
csdnceshi52
妄徒之命 you can use a = a || 42; it's more easy
接近 5 年之前 回复
csdnceshi77
狐狸.fox why not simply using the less cryptic if (typeof a === 'undefined') a = 42;?
接近 5 年之前 回复
weixin_41568127
?yb? will this work if I just call the function by using foo(); without parameters..
大约 5 年之前 回复
csdnceshi60
℡Wang Yan Also that's how it roughly looks when you compile/preprocess TypeScript function with parameters having a default value.
大约 5 年之前 回复
csdnceshi60
℡Wang Yan There were some problems with undefined not being a keyword in older javascript engines - so you could overwrite it. You can always generate an undefined by using void - for example: a = a !== void 0 ? a : "Default"; - it is ugly, and there is something fundamentally wrong with the code overwriting undefined anyway.
大约 5 年之前 回复
csdnceshi62
csdnceshi62 And we don't have to worry about a ending up as a global variable if it wasn't specified in the function call?
5 年多之前 回复
csdnceshi58
Didn"t forge Is there any reason to use typeof? It would seem simpler to just do a === undefined. Plus that way you'd get a reference error if you misspelled undefined vs. putting it in a string.
5 年多之前 回复
weixin_41568184
叼花硬汉 I know it's really minor, but I don't like how you are assigning a = a and b = b when those parameters are not undefined. Also, that ternary operator with a bit complicated condition may be hard to read for future maintainers. I would prefer following syntax: if (typeof a == 'undefined') a = 42 - no unnecessary assignment plus a little bit easier to read.
接近 6 年之前 回复
csdnceshi71
Memor.の This didn't work for me. If you pass in no value you can't use typeof on the parameter. You have to instead use var === undefined
7 年多之前 回复
weixin_41568183
零零乙 if you check against the property of an object, then typeof is redundant. function foo(data) { var bar = data.bar !== undefined ? data.bar : 'default'; } This won't throw reference errors and is concise.
7 年多之前 回复
csdnceshi78
程序go and you got extra reference errors for free of charge while trying to use undefined objects :p Even while it may work with some browsers and might be faster, null is still an object and undefined is reference to primitive type that is trying to tell that there is nothing here, not even null. See here, both cases in nutshell: JavaScript/Reference/Global_Objects/undefined.
接近 8 年之前 回复
csdnceshi79
python小菜 undefined==null (but not ===null). But if you intentionally pass null to the function, my code will not work.
接近 8 年之前 回复
csdnceshi78
程序go then it is not anymore default value and there's no point other than quickly changing a lot of values passed to functions (like using defined constants in place of null). Basically your code translates null to 42. If a is undefined in your example then it will stay undefined and it is not getting any default value.
接近 8 年之前 回复
csdnceshi79
python小菜 This is too slow, use a = ((a != null) ? a : 42);.
大约 8 年之前 回复
csdnceshi80
胖鸭 You can also encapsulate it as such: function defaultFor(arg, val) { return typeof arg !== 'undefined' ? arg : val; } and then you can call it as a = defaultFor(a, 42);
大约 8 年之前 回复
function read_file(file, delete_after) {
    delete_after = delete_after || "my default here";
    //rest of code
}

This assigns to delete_after the value of delete_after if it is not a falsey value otherwise it assigns the string "my default here". For more detail, check out Doug Crockford's survey of the language and check out the section on Operators.

This approach does not work if you want to pass in a falsey value i.e. false, null, undefined, 0 or "". If you require falsey values to be passed in you would need to use the method in Tom Ritter's answer.

When dealing with a number of parameters to a function, it is often useful to allow the consumer to pass the parameter arguments in an object and then merge these values with an object that contains the default values for the function

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;
};

to use

// 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" }); 
csdnceshi59
ℙℕℤℝ The first example is not universal because that won't work for the case with a method like setValue(v) if you pass 0 where v should be 1 by default. It will work with strings and objects only.
大约 2 年之前 回复
weixin_41568196
撒拉嘿哟木头 This works for variebles as well as objects. Thank you.
2 年多之前 回复
weixin_41568131
10.24 Also, for a junior unaware of the concept this will look really cryptic and confusing. Checking for undefined in a IF and then assigning a value is not that longer and it is much more intent revealing. You can immediately see what is it for even as a complete newbie.
接近 3 年之前 回复
csdnceshi54
hurriedly% Thankfully we now have ES6 (and Babel), so this will be more of a moot point going forward now that the language natively supports this in a sane fashion. For those not on ES6 yet, I think saying "if you require falsey values" or "if you want to pass in a falsey value" is a bit misleading, since you may be passed falsey values you didn't anticipate when writing the code, either because what you write will be used by other people, or by your future self (which is practically the same as "other people") that forgot a li'l caveat baked into old code.
3 年多之前 回复
csdnceshi76
斗士狗 suggests this approach may create a maintenance nightmare. I'd say it more strongly: It most likely WILL be a nightmare. Russ Cam wrote that this approach won't work when values that can be cast to Boolean false are used. If you use this approach, how can you be sure that your code won't be called with a false value? You can't. Therefore, this approach isn't a good idea. The only current safe approach is to use typeof and compare the results with 'undefined'.
3 年多之前 回复
csdnceshi75
衫裤跑路 Can a function even be false?
4 年多之前 回复
weixin_41568110
七度&光 or, you could just default to a falsey value - which is generally a good default anyway (eg., false for bools, empty string for strings, 0 for numbers, etc.) - in which case it doesn't really matter what was passed in.
4 年多之前 回复
weixin_41568126
乱世@小熊 This may be better this way: delete_after = typeof(delete_after) != 'undefined' ? delete_after : "my default here";
大约 5 年之前 回复
csdnceshi62
csdnceshi62 It may not work if you need falsey values but my functions will frequently take an optional options object. This is perfect for that use case: opts = opts || {}.
大约 5 年之前 回复
csdnceshi66
必承其重 | 欲带皇冠 Here is the catch : "This approach does not work if you want to pass in a falsey value i.e. false, null, undefined, 0 or "". If you require falsey values to be passed in you would need to use the method in Tom Ritter's answer." Thanks for clarifying.
6 年多之前 回复
weixin_41568184
叼花硬汉 it assigns to delete_after the value of delete_after if it is not a falsey value otherwise it assigns the string my default here. For more detail, check out Doug Crockford's survey of the lanugage and check out the section on Operators - javascript.crockford.com/survey.html
接近 8 年之前 回复
weixin_41568208
北城已荒凉 How come, in this case, delete_after doesn't get the boolean result of the expression delete_after || "my default value"?
接近 8 年之前 回复
csdnceshi54
hurriedly% Because it doesn't work for falsey values, it may create a maintenance nightmare. A bit of code that has always been passed truthy values before and suddenly fails because a falsey one is passed in should probably be avoided where a more robust approach is available.
大约 8 年之前 回复
weixin_41568184
叼花硬汉 It doesn't work for any falsey value
8 年多之前 回复
csdnceshi70
笑故挽风 This also doesn't work for 0. :(
8 年多之前 回复
weixin_41568184
叼花硬汉 I find it's adequate for most situations
11 年多之前 回复
csdnceshi65
larry*wei I find this insufficient, because I may want to pass in false.
11 年多之前 回复

I find something simple like this to be much more concise and readable personally.

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

function myFunc(x) {
  x = pick(x, 'my default');
} 
weixin_41568131
10.24 It's no longer possible to create a global variable named undefined. It's only possible to create a local variable or function parameter of that name, and if you introduce one of those into your function's lexical scope you've only got yourself to blame.
3 年多之前 回复
weixin_41568183
零零乙 It's still possible to override undefined. So, it's still a good idea to use typeof and 'undefined'.
3 年多之前 回复
weixin_41568131
10.24 what you say is correct for current JS - the older test persists because on some browsers it used to be possible to overwrite undefined with some other value, causing the test to fail.
接近 5 年之前 回复
csdnceshi73
喵-见缝插针 Don't say typeof arg == 'undefined', instead say arg === undefined
大约 5 年之前 回复
csdnceshi66
必承其重 | 欲带皇冠 I actually recommend this one, i use it and call it "por" which stands for "parameter or"
5 年多之前 回复
csdnceshi76
斗士狗 mind posting a quick demo?
大约 6 年之前 回复
csdnceshi55
~Onlooker Update: If you're using underscore.js already I find it even better to use _.defaults(iceCream, {flavor: "vanilla", sprinkles: "lots"});. Using the global namespace as shown in this answer is by many considered a bad practice. You may also consider rolling your own utility for this common task (eg. util.default(arg, "defaul value")) if don't want to use underscore, but I mostly end up using underscore sooner or later anyway no point in reinventing the wheel.
大约 6 年之前 回复

that solution is work for me in js:

function read_file(file, delete_after) {
    delete_after = delete_after || false;
    // Code
}
csdnceshi66
必承其重 | 欲带皇冠 What about delete_after = delete_after === undefined ? false : delete_after?
3 年多之前 回复
csdnceshi67
bug^君 I don't understand anything you just said.
3 年多之前 回复
weixin_41568184
叼花硬汉 it only would be true in some cases. But if you only want the default values to unset values this didn't work, because 0 or null !=== false.
3 年多之前 回复
csdnceshi73
喵-见缝插针 What happens if delete_after is 0 or null? It will not work correct for these cases.
接近 5 年之前 回复

Just use an explicit comparison with undefined.

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

As an update...with ECMAScript 6 you can FINALLY set default values in function parameter declarations like so:

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

f(1) === 50

As referenced by - http://es6-features.org/#DefaultParameterValues

csdnceshi54
hurriedly% This answer is not useful because it is a duplicate
接近 5 年之前 回复

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

Here foo() is a function which has a parameter named argValue. If we don’t pass anything in the function call here, then the function throwIfNoValue() will be called and the returned result will be assigned to the only argument argValue. This is how a function call can be used as a default parameter. Which makes the code more simplified and readable.

This example has been taken from here

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

Default Parameter Values

With ES6, you can do perhaps one of the most common idioms in JavaScript relates to setting a default value for a function parameter. The way we’ve done this for years should look quite familiar:

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

This pattern is most used, but is dangerous when we pass values like

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

Why? Because the 0 is falsy, and so the x || 11 results in 11, not the directly passed in 0. To fix this gotcha, some people will instead write the check more verbosely like this:

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

we can now examine a nice helpful syntax added as of ES6 to streamline the assignment of default values to missing arguments:

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 in a function declaration is more like x !== undefined ? x : 11 than the much more common idiom x || 11

Default Value Expressions

Function default values can be more than just simple values like 31; they can be any valid expression, even a 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

As you can see, the default value expressions are lazily evaluated, meaning they’re only run if and when they’re needed — that is, when a parameter’s argument is omitted or is undefined.

A default value expression can even be an inline function expression call — commonly referred to as an Immediately Invoked Function Expression (IIFE):

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

being a long time C++ developer (Rookie to web development :)), when I first came across this situation, I did the parameter assignment in the function definition, like it is mentioned in the question, as follows.

function myfunc(a,b=10)

But beware that it doesn't work consistently across browsers. For me it worked on chrome on my desktop, but did not work on chrome on android. Safer option, as many have mentioned above is -

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

Intention for this answer is not to repeat the same solutions, what others have already mentioned, but to inform that parameter assignment in the function definition may work on some browsers, but don't rely on it.

weixin_41568196
撒拉嘿哟木头 In case anyone's wondering, function myfunc(a,b=10) is ES6 syntax, there are links to compatibility tables in other answers.
大约 4 年之前 回复
csdnceshi52
妄徒之命 Assignment within the function definition also doesn't work in IE 11, which is the most current version of IE for Windows 8.1.
4 年多之前 回复
共21条数据 1 3 尾页
立即提问