在JavaScript中有更好的方法来执行可选函数参数吗?(复制)

时间:2021-05-26 11:01:47

This question already has an answer here:

这个问题已经有了答案:

I've always handled optional parameters in JavaScript like this:

我一直在JavaScript中处理可选参数:

function myFunc(requiredArg, optionalArg){
  optionalArg = optionalArg || 'defaultValue';

  // Do stuff
}

Is there a better way to do it?

有更好的方法吗?

Are there any cases where using || like that is going to fail?

有没有这样使用||会失败的情况?

29 个解决方案

#1


1006  

Your logic fails if optionalArg is passed, but evaluates as false - try this as an alternative

如果通过了optionalArg,那么您的逻辑将会失败,但是计算结果将是false——请尝试使用这个替代方法

if (typeof optionalArg === 'undefined') { optionalArg = 'default'; }

Or an alternative idiom:

或另一个成语:

optionalArg = (typeof optionalArg === 'undefined') ? 'default' : optionalArg;

Use whichever idiom communicates the intent best to you!

使用任何最能表达意图的习语!

#2


124  

I find this to be the simplest, most readable way:

我发现这是最简单、最易读的方式:

if (typeof myVariable === 'undefined') { myVariable = 'default'; }
//use myVariable here

Paul Dixon's answer (in my humble opinion) is less readable than this, but it comes down to preference.

Paul Dixon的回答(以我的拙见)比这个更难读懂,但归根结底是偏好。

insin's answer is much more advanced, but much more useful for big functions!

insin的答案更高级,但对大函数更有用!

EDIT 11/17/2013 9:33pm: I've created a package for Node.js that makes it easier to "overload" functions (methods) called parametric.

编辑11/17/2013 9:33pm:我为Node创建了一个包。这样更容易“重载”称为参数的函数(方法)。

#3


115  

In ECMAScript 2015 (aka "ES6") you can declare default argument values in the function declaration:

在ECMAScript 2015(又名“ES6”)中,可以在函数声明中声明默认参数值:

function myFunc(requiredArg, optionalArg = 'defaultValue') {
    // do stuff
}

More about them in this article on MDN (despite the article title, they're called "arguments," not "parameters," in JavaScript).

本文中关于MDN的更多内容(尽管文章标题是“参数”,而不是JavaScript中的“参数”)。

This is currently only supported by Firefox, but as the standard has been completed, expect support to improve rapidly.

这目前仅由Firefox支持,但随着标准的完成,预计支持将迅速得到改善。

#4


43  

If you need to chuck a literal NULL in, then you could have some issues. Apart from that, no, I think you're probably on the right track.

如果你需要将文字空值插入,那么你可能会遇到一些问题。除此之外,不,我认为你可能是在正确的轨道上。

The other method some people choose is taking an assoc array of variables iterating through the argument list. It looks a bit neater but I imagine it's a little (very little) bit more process/memory intensive.

有些人选择的另一种方法是使用一个assoc变量数组遍历参数列表。它看起来有点整洁,但我想它有点(非常少)进程/内存密集型。

function myFunction (argArray) {
    var defaults = {
        'arg1'  :   "value 1",
        'arg2'  :   "value 2",
        'arg3'  :   "value 3",
        'arg4'  :   "value 4"
    }

    for(var i in defaults) 
        if(typeof argArray[i] == "undefined") 
               argArray[i] = defaults[i];

    // ...
}

#5


32  

Ideally, you would refactor to pass an object and merge it with a default object, so the order in which arguments are passed doesn't matter (see the second section of this answer, below).

理想情况下,您可以重构以传递一个对象,并将其与一个默认对象合并,因此传递参数的顺序并不重要(请参阅下面这个答案的第二部分)。

If, however, you just want something quick, reliable, easy to use and not bulky, try this:

然而,如果你只想要一些快速、可靠、易于使用且不笨重的东西,那么试试以下方法:


A clean quick fix for any number of default arguments

  • It scales elegantly: minimal extra code for each new default
  • 它优雅地伸缩:每个新默认值都需要最少的额外代码。
  • You can paste it anywhere: just change the number of required args and variables
  • 您可以在任何地方粘贴它:只需更改所需的args和变量的数量
  • If you want to pass undefined to an argument with a default value, this way, the variable is set as undefined. Most other options on this page would replace undefined with the default value.
  • 如果您希望将undefined传递给具有默认值的参数,则将变量设置为undefined。本页的大多数其他选项将用默认值替换未定义的。

Here's an example for providing defaults for three optional arguments (with two required arguments)

这里有一个为三个可选参数(包含两个必需参数)提供默认值的示例

function myFunc( requiredA, requiredB,  optionalA, optionalB, optionalC ) {

  switch (arguments.length - 2) { // 2 is the number of required arguments
    case 0:  optionalA = 'Some default';
    case 1:  optionalB = 'Another default';
    case 2:  optionalC = 'Some other default';
    // no breaks between cases: each case implies the next cases are also needed
  }

}

Simple demo. This is similar to roenving's answer, but easily extendible for any number of default arguments, easier to update, and using arguments not Function.arguments.

简单的演示。这类似于roenving的回答,但是对于任意数量的默认参数来说,它很容易扩展,易于更新,并且使用参数而不是Function.arguments。


Passing and merging objects for more flexibility

The above code, like many ways of doing default arguments, can't pass arguments out of sequence, e.g., passing optionalC but leaving optionalB to fall back to its default.

上面的代码,像许多处理默认参数的方法一样,不能按照顺序传递参数,例如,传递optionalC,而让optionalB返回到默认值。

A good option for that is to pass objects and merge with a default object. This is also good for maintainability (just take care to keep your code readable, so future collaborators won't be left guessing about the possible contents of the objects you pass around).

一个好的选择是传递对象并与默认对象合并。这对可维护性也有好处(只要注意使代码可读,这样将来的协作者就不会对您传递的对象的可能内容产生怀疑)。

Example using jQuery. If you don't use jQuery, you could instead use Underscore's _.defaults(object, defaults) or browse these options:

使用jQuery示例。如果不使用jQuery,可以使用下划线的_.defaults(对象,默认)或浏览以下选项:

function myFunc( args ) {
  var defaults = {
    optionalA: 'Some default',
    optionalB: 'Another default',
    optionalC: 'Some other default'
  };
  args = $.extend({}, defaults, args);
}

Here's a simple example of it in action.

这里有一个简单的例子。

#6


17  

You can use some different schemes for that. I've always tested for arguments.length:

你可以用一些不同的方案。我总是测试辩论。

function myFunc(requiredArg, optionalArg){
  optionalArg = myFunc.arguments.length<2 ? 'defaultValue' : optionalArg;

  ...

-- doing so, it can't possibly fail, but I don't know if your way has any chance of failing, just now I can't think up a scenario, where it actually would fail ...

——这样做,它不可能失败,但我不知道你的方式是否有失败的可能,刚才我想不出一个可能会失败的场景……

And then Paul provided one failing scenario !-)

然后保罗提供了一个失败的场景!

#7


13  

Similar to Oli's answer, I use an argument Object and an Object which defines the default values. With a little bit of sugar...

与奥利的答案相似,我使用一个参数对象和一个定义默认值的对象。加一点糖……

/**
 * Updates an object's properties with other objects' properties. All
 * additional non-falsy arguments will have their properties copied to the
 * destination object, in the order given.
 */
function extend(dest) {
  for (var i = 1, l = arguments.length; i < l; i++) {
    var src = arguments[i]
    if (!src) {
      continue
    }
    for (var property in src) {
      if (src.hasOwnProperty(property)) {
        dest[property] = src[property]
      }
    }
  }
  return dest
}

/**
 * Inherit another function's prototype without invoking the function.
 */
function inherits(child, parent) {
  var F = function() {}
  F.prototype = parent.prototype
  child.prototype = new F()
  child.prototype.constructor = child
  return child
}

...this can be made a bit nicer.

…这可以做得更好一点。

function Field(kwargs) {
  kwargs = extend({
    required: true, widget: null, label: null, initial: null,
    helpText: null, errorMessages: null
  }, kwargs)
  this.required = kwargs.required
  this.label = kwargs.label
  this.initial = kwargs.initial
  // ...and so on...
}

function CharField(kwargs) {
  kwargs = extend({
    maxLength: null, minLength: null
  }, kwargs)
  this.maxLength = kwargs.maxLength
  this.minLength = kwargs.minLength
  Field.call(this, kwargs)
}
inherits(CharField, Field)

What's nice about this method?

这个方法有什么好处?

  • You can omit as many arguments as you like - if you only want to override the value of one argument, you can just provide that argument, instead of having to explicitly pass undefined when, say there are 5 arguments and you only want to customise the last one, as you would have to do with some of the other methods suggested.
  • 你可以省略尽可能多的参数——如果你只想覆盖一个参数的值,你可以提供这一观点,而不是显式地通过定义时,说有5个参数,你只想定制最后一个,你会与其他的一些方法建议。
  • When working with a constructor Function for an object which inherits from another, it's easy to accept any arguments which are required by the constructor of the Object you're inheriting from, as you don't have to name those arguments in your constructor signature, or even provide your own defaults (let the parent Object's constructor do that for you, as seen above when CharField calls Field's constructor).
  • 当处理一个继承自另一个对象的构造函数,很容易接受任何参数的构造函数所需的对象你继承,正如你不需要名字这些参数构造函数签名,甚至提供自己的违约(让父对象的构造函数为你这么做,如上图所示,当CharField调用的构造函数)。
  • Child objects in inheritance hierarchies can customise arguments for their parent constructor as they see fit, enforcing their own default values or ensuring that a certain value will always be used.
  • 继承层次结构中的子对象可以根据父构造函数的需要定制参数,执行自己的默认值,或者确保始终使用某个值。

#8


8  

If you're using defaults extensively, this seems much more readable:

如果你大量使用默认值,这看起来可读性更强:

function usageExemple(a,b,c,d){
    //defaults
    a=defaultValue(a,1);
    b=defaultValue(b,2);
    c=defaultValue(c,4);
    d=defaultValue(d,8);

    var x = a+b+c+d;
    return x;
}

Just declare this function on the global escope.

在全局escope上声明这个函数。

function defaultValue(variable,defaultValue){
    return(typeof variable!=='undefined')?(variable):(defaultValue);
}

Usage pattern fruit = defaultValue(fruit,'Apple');

使用模式果= defaultValue(水果,“苹果”);

*PS you can rename the defaultValue function to a short name, just don't use default it's a reserved word in javascript.

*PS可以将defaultValue函数重命名为短名称,但不要使用默认值,这是javascript中的保留字。

#9


8  

Loose type checking

松散类型检查

Easy to write, but 0, '', false, null and undefined will be converted to default value, which might not be expected outcome.

易于编写,但是0,”,false, null和undefined将被转换为默认值,这可能不是预期的结果。

function myFunc(requiredArg, optionalArg) {
    optionalArg = optionalArg || 'defaultValue';
}

Strict type checking

严格的类型检查

Longer, but covers majority of cases. Only case where it incorrectly assigns default value is when we pass undefined as parameter.

更长,但涵盖了大多数情况。只有当我们将未定义的参数传递给它时,它才会不正确地分配默认值。

function myFunc(requiredArg, optionalArg) {
    optionalArg = typeof optionalArg !== 'undefined' ? optionalArg : 'defaultValue';
}

Checking arguments variable

检查参数变量

Catches all cases but is the most clumsy to write.

抓住所有的情况,但写起来最笨拙。

function myFunc(requiredArg, optionalArg1, optionalArg2) {
    optionalArg1 = arguments.length > 1 ? optionalArg1 : 'defaultValue';
    optionalArg2 = arguments.length > 2 ? optionalArg2 : 'defaultValue';
}

ES6

ES6

Unfortunately this has very poor browser support at the moment

不幸的是,目前这种浏览器的支持非常糟糕

function myFunc(requiredArg, optionalArg = 'defaultValue') {

}

#10


5  

With ES2015/ES6 you can take advantage of Object.assign which can replace $.extend() or _.defaults()

有了ES2015/ES6,你可以充分利用对象。可以替换$.extend()或_.defaults()的赋值

function myFunc(requiredArg, options = {}) {
  const defaults = {
    message: 'Hello',
    color: 'red',
    importance: 1
  };

  const settings = Object.assign({}, defaults, options);

  // do stuff
}

You can also use defaults arguments like this

您还可以使用这样的默认参数

function myFunc(requiredArg, { message: 'Hello', color: 'red', importance: 1 } = {}) {
  // do stuff
}

#11


3  

If you're using the Underscore library (you should, it's an awesome library):

如果您正在使用下划线库(您应该这样做,它是一个很棒的库):

_.defaults(optionalArg, 'defaultValue');

#12


3  

I am used to seeing a few basic variations on handling optional variables. Sometimes, the relaxed versions are useful.

我习惯于看到一些处理可选变量的基本变化。有时,放松的版本是有用的。

function foo(a, b, c) {
  a = a || "default";   // Matches 0, "", null, undefined, NaN, false.
  a || (a = "default"); // Matches 0, "", null, undefined, NaN, false.

  if (b == null) { b = "default"; } // Matches null, undefined.

  if (typeof c === "undefined") { c = "default"; } // Matches undefined.
}

The falsy default used with variable a is, for example, used extensively in Backbone.js.

例如,变量a使用的falsy缺省值在Backbone.js中使用得很广泛。

#13


2  

Landed to this question, searching for default parameters in EcmaScript 2015, thus just mentioning...

回答了这个问题,搜索了EcmaScript 2015的默认参数,所以只提到了……

With ES6 we can do default parameters:

使用ES6,我们可以做默认参数:

function doSomething(optionalParam = "defaultValue"){
    console.log(optionalParam);//not required to check for falsy values
}

doSomething(); //"defaultValue"
doSomething("myvalue"); //"myvalue"

#14


2  

I don't know why @Paul's reply is downvoted, but the validation against null is a good choice. Maybe a more affirmative example will make better sense:

我不知道为什么@Paul的回复被否决,但是对null的验证是一个很好的选择。也许一个更肯定的例子更有意义:

In JavaScript a missed parameter is like a declared variable that is not initialized (just var a1;). And the equality operator converts the undefined to null, so this works great with both value types and objects, and this is how CoffeeScript handles optional parameters.

在JavaScript中,缺失的参数就像未初始化的声明变量(只是var a1;)。等式运算符将undefined转换为null,因此这对于值类型和对象都很有效,这就是CoffeeScript处理可选参数的方式。

function overLoad(p1){
    alert(p1 == null); // Caution, don't use the strict comparison: === won't work.
    alert(typeof p1 === 'undefined');
}

overLoad(); // true, true
overLoad(undefined); // true, true. Yes, undefined is treated as null for equality operator.
overLoad(10); // false, false


function overLoad(p1){
    if (p1 == null) p1 = 'default value goes here...';
    //...
}

Though, there are concerns that for the best semantics is typeof variable === 'undefined' is slightly better. I'm not about to defend this since it's the matter of the underlying API how a function is implemented; it should not interest the API user.

尽管如此,仍然有人担心,对于最好的语义来说,typeof变量== '未定义'稍微好一些。我不打算对此进行辩护,因为实现函数的关键在于底层API;它不应该引起API用户的兴趣。

I should also add that here's the only way to physically make sure any argument were missed, using the in operator which unfortunately won't work with the parameter names so have to pass an index of the arguments.

我还应该补充一点,这是确保任何参数被忽略的唯一方法,使用的操作符很遗憾不能使用参数名,因此必须传递参数的索引。

function foo(a, b) {
    // Both a and b will evaluate to undefined when used in an expression
    alert(a); // undefined
    alert(b); // undefined

    alert("0" in arguments); // true
    alert("1" in arguments); // false
}

foo (undefined);

#15


2  

The test for undefined is unnecessary and isn't as robust as it could be because, as user568458 pointed out, the solution provided fails if null or false is passed. Users of your API might think false or null would force the method to avoid that parameter.

对未定义的测试是不必要的,并且不像可能的那样健壮,因为user568458指出,如果通过null或false,则提供的解决方案失败。API的用户可能认为false或null会迫使方法避免该参数。

function PaulDixonSolution(required, optionalArg){
   optionalArg = (typeof optionalArg === "undefined") ? "defaultValue" : optionalArg;
   console.log(optionalArg);
};
PaulDixonSolution("required");
PaulDixonSolution("required", "provided");
PaulDixonSolution("required", null);
PaulDixonSolution("required", false);

The result is:

其结果是:

defaultValue
provided
null
false

Those last two are potentially bad. Instead try:

最后两种可能是坏的。而不是尝试:

function bulletproof(required, optionalArg){
   optionalArg = optionalArg ? optionalArg : "defaultValue";;
   console.log(optionalArg);
};
bulletproof("required");
bulletproof("required", "provided");
bulletproof("required", null);
bulletproof("required", false);

Which results in:

结果:

defaultValue
provided
defaultValue
defaultValue

The only scenario where this isn't optimal is when you actually have optional parameters that are meant to be booleans or intentional null.

唯一不理想的情况是,当您实际拥有可选参数时,该参数应该是布尔值或故意空值。

#16


2  

I tried some options mentioned in here and performance tested them. At this moment the logicalor seems to be the fastest. Although this is subject of change over time (different JavaScript engine versions).

我尝试了一些在这里提到的选项,并进行了性能测试。此时此刻,逻辑学家似乎是最快的。尽管这是随时间变化的主题(不同的JavaScript引擎版本)。

These are my results (Microsoft Edge 20.10240.16384.0):

这是我的结果(微软Edge 20.10240.16384.0):

Function executed            Operations/sec     Statistics
TypeofFunction('test');          92,169,505     ±1.55%   9% slower
SwitchFuntion('test');            2,904,685     ±2.91%  97% slower
ObjectFunction({param1: 'test'});   924,753     ±1.71%  99% slower
LogicalOrFunction('test');      101,205,173     ±0.92%     fastest
TypeofFunction2('test');         35,636,836     ±0.59%  65% slower

This performance test can be easily replicated on: http://jsperf.com/optional-parameters-typeof-vs-switch/2

这个性能测试可以在http://jsperf.com/optional-parameters-typeof-vs-switch/2上轻松复制

This is the code of the test:

这是测试的代码:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
    Benchmark.prototype.setup = function() {
        function TypeofFunction(param1, optParam1, optParam2, optParam3) {
            optParam1 = (typeof optParam1 === "undefined") ? "Some default" : optParam1;
            optParam2 = (typeof optParam2 === "undefined") ? "Another default" : optParam2;
            optParam3 = (typeof optParam3 === "undefined") ? "Some other default" : optParam3;
        }

        function TypeofFunction2(param1, optParam1, optParam2, optParam3) {
            optParam1 = defaultValue(optParam1, "Some default");
            optParam2 = defaultValue(optParam2, "Another default");
            optParam3 = defaultValue(optParam3, "Some other default");
        }

        function defaultValue(variable, defaultValue) {
            return (typeof variable !== 'undefined') ? (variable) : (defaultValue);
        }

        function SwitchFuntion(param1, optParam1, optParam2, optParam3) {
            switch (arguments.length - 1) { // <-- 1 is number of required arguments
                case 0:
                    optParam1 = 'Some default';
                case 1:
                    optParam2 = 'Another default';
                case 2:
                    optParam3 = 'Some other default';
            }
        }

        function ObjectFunction(args) {
            var defaults = {
                optParam1: 'Some default',
                optParam2: 'Another default',
                optParam3: 'Some other default'
            }
            args = $.extend({}, defaults, args);
        }

        function LogicalOrFunction(param1, optParam1, optParam2, optParam3) {
            optParam1 || (optParam1 = 'Some default');
            optParam2 || (optParam1 = 'Another default');
            optParam3 || (optParam1 = 'Some other default');
        }
    };
</script>

#17


1  

This is what I ended up with:

这就是我最后得出的结论:

function WhoLikesCake(options) {
  options = options || {};
  var defaultOptions = {
    a : options.a || "Huh?",
    b : options.b || "I don't like cake."
  }
  console.log('a: ' + defaultOptions.b + ' - b: ' + defaultOptions.b);

  // Do more stuff here ...
}

Called like this:

像这样:

WhoLikesCake({ b : "I do" });

#18


1  

Folks -

人- - - - - -

After looking at these and other solutions, I tried a number of them out using a snippet of code originally from W3Schools as a base. You can find what works in the following. Each of the items commented out work as well and are that way to allow you to experiment simply by removing individual comments. To be clear, it is the "eyecolor" parameter that is not being defined.

在查看了这些解决方案和其他解决方案之后,我尝试使用W3Schools的一段代码作为基础。您可以在下面找到有效的方法。每个条目都注释掉了工作,这样您就可以通过删除单独的注释进行实验。需要明确的是,“眼镜颜色”参数没有被定义。

function person(firstname, lastname, age, eyecolor)
{
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
this.eyecolor = eyecolor;
// if(null==eyecolor)
//   this.eyecolor = "unknown1";
//if(typeof(eyecolor)==='undefined') 
//   this.eyecolor = "unknown2";
// if(!eyecolor)
//   this.eyecolor = "unknown3";
this.eyecolor = this.eyecolor || "unknown4";
}

var myFather = new person("John", "Doe", 60);
var myMother = new person("Sally", "Rally", 48, "green");

var elem = document.getElementById("demo");
elem.innerHTML = "My father " +
              myFather.firstname + " " +
              myFather.lastname + " is " +
              myFather.age + " with " +
              myFather.eyecolor + " eyes.<br/>" +
              "My mother " +
              myMother.firstname + " " +
              myMother.lastname + " is " +
              myMother.age + " with " +
              myMother.eyecolor + " eyes."; 

#19


1  

function Default(variable, new_value)
{
    if(new_value === undefined) { return (variable === undefined) ? null : variable; }
    return (variable === undefined) ? new_value : variable;
}

var a = 2, b = "hello", c = true, d;

var test = Default(a, 0),
test2 = Default(b, "Hi"),
test3 = Default(c, false),
test4 = Default(d, "Hello world");

window.alert(test + "\n" + test2 + "\n" + test3 + "\n" + test4);

http://jsfiddle.net/mq60hqrf/

http://jsfiddle.net/mq60hqrf/

#20


1  

During a project I noticed I was repeating myself too much with the optional parameters and settings, so I made a class that handles the type checking and assigns a default value which results in neat and readable code. See example and let me know if this works for you.

在一个项目中,我注意到我在可选参数和设置上重复了太多,所以我创建了一个类来处理类型检查并分配一个默认值,从而生成整洁且可读的代码。看看例子,让我知道这是否适合你。

var myCar           = new Car('VW', {gearbox:'automatic', options:['radio', 'airbags 2x']});
var myOtherCar      = new Car('Toyota');

function Car(brand, settings) {
    this.brand      = brand;

    // readable and adjustable code
    settings        = DefaultValue.object(settings, {});
    this.wheels     = DefaultValue.number(settings.wheels, 4);
    this.hasBreaks  = DefaultValue.bool(settings.hasBreaks, true);
    this.gearbox    = DefaultValue.string(settings.gearbox, 'manual');
    this.options    = DefaultValue.array(settings.options, []);

    // instead of doing this the hard way
    settings        = settings || {};
    this.wheels     = (!isNaN(settings.wheels)) ? settings.wheels : 4;
    this.hasBreaks  = (typeof settings.hasBreaks !== 'undefined') ? (settings.hasBreaks === true) : true;
    this.gearbox    = (typeof settings.gearbox === 'string') ? settings.gearbox : 'manual';
    this.options    = (typeof settings.options !== 'undefined' && Array.isArray(settings.options)) ? settings.options : [];
}

Using this class:

使用这个类:

(function(ns) {

    var DefaultValue = {

        object: function(input, defaultValue) {
            if (typeof defaultValue !== 'object') throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined') ? input : defaultValue;
        },

        bool: function(input, defaultValue) {
            if (typeof defaultValue !== 'boolean') throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined') ? (input === true) : defaultValue;
        },

        number: function(input, defaultValue) {
            if (isNaN(defaultValue)) throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined' && !isNaN(input)) ? parseFloat(input) : defaultValue;
        },

        // wrap the input in an array if it is not undefined and not an array, for your convenience
        array: function(input, defaultValue) {
            if (typeof defaultValue === 'undefined') throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined') ? (Array.isArray(input) ? input : [input]) : defaultValue;
        },

        string: function(input, defaultValue) {
            if (typeof defaultValue !== 'string') throw new Error('invalid defaultValue type');
            return (typeof input === 'string') ? input : defaultValue;
        },

    };

    ns.DefaultValue = DefaultValue;

}(this));

#21


1  

Here is my solution. With this you can leave any parameter you want. The order of the optional parameters is not important and you can add custom validation.

这是我的解决方案。有了这个,你可以留下任何你想要的参数。可选参数的顺序并不重要,您可以添加自定义验证。

function YourFunction(optionalArguments) {
            //var scope = this;

            //set the defaults
            var _value1 = 'defaultValue1';
            var _value2 = 'defaultValue2';
            var _value3 = null;
            var _value4 = false;

            //check the optional arguments if they are set to override defaults...
            if (typeof optionalArguments !== 'undefined') {

                if (typeof optionalArguments.param1 !== 'undefined')
                    _value1 = optionalArguments.param1;

                if (typeof optionalArguments.param2 !== 'undefined')
                    _value2 = optionalArguments.param2;

                if (typeof optionalArguments.param3 !== 'undefined')
                    _value3 = optionalArguments.param3;

                if (typeof optionalArguments.param4 !== 'undefined')
                    //use custom parameter validation if needed, in this case for javascript boolean
                   _value4 = (optionalArguments.param4 === true || optionalArguments.param4 === 'true');
            }

            console.log('value summary of function call:');
            console.log('value1: ' + _value1);
            console.log('value2: ' + _value2);
            console.log('value3: ' + _value3);
            console.log('value4: ' + _value4);
            console.log('');
        }


        //call your function in any way you want. You can leave parameters. Order is not important. Here some examples:
        YourFunction({
            param1: 'yourGivenValue1',
            param2: 'yourGivenValue2',
            param3: 'yourGivenValue3',
            param4: true,
        });

        //order is not important
        YourFunction({
            param4: false,
            param1: 'yourGivenValue1',
            param2: 'yourGivenValue2',
        });

        //uses all default values
        YourFunction();

        //keeps value4 false, because not a valid value is given
        YourFunction({
            param4: 'not a valid bool'
        });

#22


1  

  1. arg || 'default' is a great way and works for 90% of cases

    arg || 'default'是一个很好的方法,适用于90%的情况。

  2. It fails when you need to pass values that might be 'falsy'

    当您需要传递可能是“falsy”的值时,它会失败

    • false
    • 0
    • 0
    • NaN
    • ""
    • ”“

    For these cases you will need to be a bit more verbose and check for undefined

    对于这些情况,您需要更详细一些,并检查未定义

  3. Also be careful when you have optional arguments first, you have to be aware of the types of all of your arguments

    还要注意,当您首先有可选参数时,您必须注意所有参数的类型

#23


0  

Correct me if I'm wrong, but this seems like the simplest way (for one argument, anyway):

如果我错了请纠正我,但这似乎是最简单的方法(不管怎样,对于一个论点):

function myFunction(Required,Optional)
{
    if (arguments.length<2) Optional = "Default";
    //Your code
}

#24


0  

Those ones are shorter than the typeof operator version.

这些比运算符类型要短。

function foo(a, b) {
    a !== undefined || (a = 'defaultA');
    if(b === undefined) b = 'defaultB';
    ...
}

#25


0  

In all cases where optionalArg is falsy you will end up with defaultValue.

在所有的情况下,选择阿拉格是假的,你最终会得到默认值。

function myFunc(requiredArg, optionalArg) {
    optionalArg = optionalArg || 'defaultValue';
    console.log(optionalArg);
    // Do stuff
}
myFunc(requiredArg);
myFunc(requiredArg, null);
myFunc(requiredArg, undefined);
myFunc(requiredArg, "");
myFunc(requiredArg, 0);
myFunc(requiredArg, false);

All of the above log defaultValue, because all of 6 are falsy. In case 4, 5, 6 you might not be interested to set optionalArg as defaultValue, but it sets since they are falsy.

上面所有的log defaultValue,因为所有6个都是假的。在情形4,5,6中,您可能对将optionalArg设置为defaultValue不感兴趣,但它会设置,因为它们是假的。

#26


-1  

I suggest you to use ArgueJS this way:

我建议你这样使用论述:

function myFunc(){
  arguments = __({requiredArg: undefined, optionalArg: [undefined: 'defaultValue'})

  //do stuff, using arguments.requiredArg and arguments.optionalArg
  //    to access your arguments

}

You can also replace undefined by the type of the argument you expect to receive, like this:

你也可以用你期望接收到的参数类型来替换未定义的参数,如下所示:

function myFunc(){
  arguments = __({requiredArg: Number, optionalArg: [String: 'defaultValue'})

  //do stuff, using arguments.requiredArg and arguments.optionalArg
  //    to access your arguments

}

#27


-1  

It seems that the safest way - to deal with all \ any falsy types of supplied arguments before deciding to use the default - is to check for the existence\presence of the optional argument in the invoked function.

似乎最安全的方法——在决定使用默认参数之前处理所有的错误类型的参数——是检查被调用函数中可选参数的存在性。

Relying on the arguments object member creation which doesn't even get created if the argument is missing, regardless of the fact that it might be declared, we can write your function like this:

依赖于参数对象成员的创建,即使参数缺失也不会被创建,不管它是否被声明,我们可以这样写你的函数:

  function myFunc(requiredArg, optionalArg){
        optionalArg = 1 in arguments ? optionalArg : 'defaultValue';
  //do stuff
  }

Utilizing this behavior: We can safely check for any missing values on arguments list arbitrarily and explicitly whenever we need to make sure the function gets a certain value required in its procedure.

利用这种行为:当我们需要确保函数在其过程中获得特定的值时,我们可以安全地任意和显式地检查参数列表上的任何缺失值。

In the following demo code we will deliberately put a typeless and valueless undefined as a default value to be able to determine whether it might fail on falsy argument values, such as 0 false etc., or if it behaves as expected.

在下面的演示代码中,我们将故意将一个无类型和无值的未定义值作为默认值,以确定它是否可能在错误的参数值(如0 false等)上失败,或者它是否按预期运行。

function argCheck( arg1, arg2, arg3 ){

       arg1 = 0 in arguments || undefined;
       arg2 = 1 in arguments || false;
       arg3 = 2 in arguments || 0;
   var arg4 = 3 in arguments || null;

   console.log( arg1, arg2, arg3, arg4 ) 
}

Now, checking few falsy argument-values to see if their presence is correctly detected and therefore evaluates to true:

现在,检查一些假的参数值,看看它们的存在是否被正确地检测到,因此评估为true:

argCheck( "", 0, false, null );
>> true true true true

Which means -they didn't fail the recognition of/as expected argument values. Here we have a check with all arguments missing, which according to our algo should acquire their default values even if they're falsy.

也就是说,它们没有忽略对期望参数值的识别。这里我们有一个所有参数缺失的检查,根据algo,它应该获取它们的默认值,即使它们是假的。

argCheck( );
>> undefined false 0 null

As we can see, the arguments arg1, arg2, arg3 and the undeclared arg4, are returning their exact default values, as ordered. Because we've now made sure that it works, we can rewrite the function which will actually be able to use them as in the first example by using: either if or a ternary condition.

如我们所见,参数arg1、arg2、arg3和未声明的arg4按照顺序返回它们的默认值。因为我们已经确定它是可行的,我们可以重写这个函数它实际上可以像第一个例子一样使用它们:if或三元条件。

On functions that have more than one optional argument, - a loop through, might have saved us some bits. But since argument names don't get initialized if their values are not supplied, we cannot access them by names anymore even if we've programmatically written a default value, we can only access them by arguments[index] which useless code readability wise.

对于具有多个可选参数的函数——循环遍历,可能会为我们节省一些比特。但是,既然参数名称没有被初始化,如果它们的值没有被提供,我们就不能再通过名称访问它们了,即使我们以编程的方式编写了一个默认值,我们也只能通过参数[索引]来访问它们,这些参数是无用的代码可读性的。

But aside from this inconvenience, which in certain coding situations might be fully acceptable, there's another unaccounted problem for multiple and arbitrary number of argument defaults. Which may and should be considered a bug, as we can no longer skip arguments, as we once might have been able to, without giving a value, in a syntax such as:

但是,除了这种不便之外(在某些编码情况下可能完全可以接受),还有另一个未解释的问题,即多个或任意数量的参数的缺省值。这可能也应该被认为是一个bug,因为我们再也不能跳过参数了,因为我们曾经可以不给出一个值,使用如下语法:

argCheck("a",,22,{});

because it will throw! Which makes it impossible for us to substitute our argument with a specific falsy type of our desired default value. Which is stupid, since the arguments object is an array-like object and is expected to support this syntax and convention as is, natively or by default!

因为它将抛出!这就使得我们不可能用我们想要的默认值的一种特定的虚假类型来替代我们的论点。这是很愚蠢的,因为arguments对象是一个类数组的对象,并且期望它能够支持这种语法和约定,就像它本身或默认的那样!

Because of this shortsighted decision we can no longer hope to write a function like this:

由于这个短视的决定,我们再也不能指望写出这样的函数:

function argCheck( ) {
    var _default = [undefined, 0, false, null ],
        _arg = arguments;

 for( var x in _default ) {
         x in _arg ? 1 : _arg[x] = _default[x];
        }
    console.log( _arg[0],_arg[1],_arg[2],_arg[3] );
}

in which case, we would be able to write each default value of a desired type in arguments row and be able to at least access them by args.index.

在这种情况下,我们可以在arguments .index中写入所需类型的每个默认值,并且至少可以通过args.index访问它们。

For instance this function call would yield:

例如,这个函数调用将产生:

argCheck();
>>undefined 0 false null

as defined in our default array of arguments values. However the following is still possible:

在参数值的默认数组中定义。但是,仍有可能有下列情况:

argCheck({})
>>Object {  } 0 false null

argCheck({}, [])
>>Object {  } Array [  ] false null

But regretfully not:

但遗憾的是:

 argCheck("a",,,22);
 >>SyntaxError: expected expression, got ','

Which would otherwise be logging:

否则将记录日志:

>>a 0 false 22

but that's in a better world! However - for the original question - the topmost function will do just fine. e.g.:

但那是在一个更好的世界!然而,对于最初的问题,最上面的函数会做得很好。例如:

function argCheck( arg, opt ) {
         1 in arguments ? 1 : opt = "default";
         console.log( arg, opt );
}

p.s.: sorry for not preserving the types of chosen defaults in my argument inputs while writing them.

注。:抱歉,在编写参数输入时没有保存所选择的默认值类型。

#28


-1  

Some code IntelliSense tools, in particular the WebStorm IDE and perhaps jshint, give warnings when you call a function with fewer arguments than declared:

一些代码智能感知工具,特别是WebStorm IDE,可能还有jshint,当你调用一个参数少于声明的函数时,会给出警告:

function foo(a, b) {
    if (typeof b === 'undefined') {
        b = 5;
    }
    …
}

foo(1); /* Warning */

You can instead do:

你可以做的:

function foo(a /*, b */) {
    var b = arguments.length > 1 ? arguments[1] : 2;
    …
}

foo(1);

Note that the b argument is declared in a comment for clarity.

注意,b参数是在注释中声明的,以保持清晰。

#29


-2  

function foo(requiredArg){
  if(arguments.length>1) var optionalArg = arguments[1];
}

#1


1006  

Your logic fails if optionalArg is passed, but evaluates as false - try this as an alternative

如果通过了optionalArg,那么您的逻辑将会失败,但是计算结果将是false——请尝试使用这个替代方法

if (typeof optionalArg === 'undefined') { optionalArg = 'default'; }

Or an alternative idiom:

或另一个成语:

optionalArg = (typeof optionalArg === 'undefined') ? 'default' : optionalArg;

Use whichever idiom communicates the intent best to you!

使用任何最能表达意图的习语!

#2


124  

I find this to be the simplest, most readable way:

我发现这是最简单、最易读的方式:

if (typeof myVariable === 'undefined') { myVariable = 'default'; }
//use myVariable here

Paul Dixon's answer (in my humble opinion) is less readable than this, but it comes down to preference.

Paul Dixon的回答(以我的拙见)比这个更难读懂,但归根结底是偏好。

insin's answer is much more advanced, but much more useful for big functions!

insin的答案更高级,但对大函数更有用!

EDIT 11/17/2013 9:33pm: I've created a package for Node.js that makes it easier to "overload" functions (methods) called parametric.

编辑11/17/2013 9:33pm:我为Node创建了一个包。这样更容易“重载”称为参数的函数(方法)。

#3


115  

In ECMAScript 2015 (aka "ES6") you can declare default argument values in the function declaration:

在ECMAScript 2015(又名“ES6”)中,可以在函数声明中声明默认参数值:

function myFunc(requiredArg, optionalArg = 'defaultValue') {
    // do stuff
}

More about them in this article on MDN (despite the article title, they're called "arguments," not "parameters," in JavaScript).

本文中关于MDN的更多内容(尽管文章标题是“参数”,而不是JavaScript中的“参数”)。

This is currently only supported by Firefox, but as the standard has been completed, expect support to improve rapidly.

这目前仅由Firefox支持,但随着标准的完成,预计支持将迅速得到改善。

#4


43  

If you need to chuck a literal NULL in, then you could have some issues. Apart from that, no, I think you're probably on the right track.

如果你需要将文字空值插入,那么你可能会遇到一些问题。除此之外,不,我认为你可能是在正确的轨道上。

The other method some people choose is taking an assoc array of variables iterating through the argument list. It looks a bit neater but I imagine it's a little (very little) bit more process/memory intensive.

有些人选择的另一种方法是使用一个assoc变量数组遍历参数列表。它看起来有点整洁,但我想它有点(非常少)进程/内存密集型。

function myFunction (argArray) {
    var defaults = {
        'arg1'  :   "value 1",
        'arg2'  :   "value 2",
        'arg3'  :   "value 3",
        'arg4'  :   "value 4"
    }

    for(var i in defaults) 
        if(typeof argArray[i] == "undefined") 
               argArray[i] = defaults[i];

    // ...
}

#5


32  

Ideally, you would refactor to pass an object and merge it with a default object, so the order in which arguments are passed doesn't matter (see the second section of this answer, below).

理想情况下,您可以重构以传递一个对象,并将其与一个默认对象合并,因此传递参数的顺序并不重要(请参阅下面这个答案的第二部分)。

If, however, you just want something quick, reliable, easy to use and not bulky, try this:

然而,如果你只想要一些快速、可靠、易于使用且不笨重的东西,那么试试以下方法:


A clean quick fix for any number of default arguments

  • It scales elegantly: minimal extra code for each new default
  • 它优雅地伸缩:每个新默认值都需要最少的额外代码。
  • You can paste it anywhere: just change the number of required args and variables
  • 您可以在任何地方粘贴它:只需更改所需的args和变量的数量
  • If you want to pass undefined to an argument with a default value, this way, the variable is set as undefined. Most other options on this page would replace undefined with the default value.
  • 如果您希望将undefined传递给具有默认值的参数,则将变量设置为undefined。本页的大多数其他选项将用默认值替换未定义的。

Here's an example for providing defaults for three optional arguments (with two required arguments)

这里有一个为三个可选参数(包含两个必需参数)提供默认值的示例

function myFunc( requiredA, requiredB,  optionalA, optionalB, optionalC ) {

  switch (arguments.length - 2) { // 2 is the number of required arguments
    case 0:  optionalA = 'Some default';
    case 1:  optionalB = 'Another default';
    case 2:  optionalC = 'Some other default';
    // no breaks between cases: each case implies the next cases are also needed
  }

}

Simple demo. This is similar to roenving's answer, but easily extendible for any number of default arguments, easier to update, and using arguments not Function.arguments.

简单的演示。这类似于roenving的回答,但是对于任意数量的默认参数来说,它很容易扩展,易于更新,并且使用参数而不是Function.arguments。


Passing and merging objects for more flexibility

The above code, like many ways of doing default arguments, can't pass arguments out of sequence, e.g., passing optionalC but leaving optionalB to fall back to its default.

上面的代码,像许多处理默认参数的方法一样,不能按照顺序传递参数,例如,传递optionalC,而让optionalB返回到默认值。

A good option for that is to pass objects and merge with a default object. This is also good for maintainability (just take care to keep your code readable, so future collaborators won't be left guessing about the possible contents of the objects you pass around).

一个好的选择是传递对象并与默认对象合并。这对可维护性也有好处(只要注意使代码可读,这样将来的协作者就不会对您传递的对象的可能内容产生怀疑)。

Example using jQuery. If you don't use jQuery, you could instead use Underscore's _.defaults(object, defaults) or browse these options:

使用jQuery示例。如果不使用jQuery,可以使用下划线的_.defaults(对象,默认)或浏览以下选项:

function myFunc( args ) {
  var defaults = {
    optionalA: 'Some default',
    optionalB: 'Another default',
    optionalC: 'Some other default'
  };
  args = $.extend({}, defaults, args);
}

Here's a simple example of it in action.

这里有一个简单的例子。

#6


17  

You can use some different schemes for that. I've always tested for arguments.length:

你可以用一些不同的方案。我总是测试辩论。

function myFunc(requiredArg, optionalArg){
  optionalArg = myFunc.arguments.length<2 ? 'defaultValue' : optionalArg;

  ...

-- doing so, it can't possibly fail, but I don't know if your way has any chance of failing, just now I can't think up a scenario, where it actually would fail ...

——这样做,它不可能失败,但我不知道你的方式是否有失败的可能,刚才我想不出一个可能会失败的场景……

And then Paul provided one failing scenario !-)

然后保罗提供了一个失败的场景!

#7


13  

Similar to Oli's answer, I use an argument Object and an Object which defines the default values. With a little bit of sugar...

与奥利的答案相似,我使用一个参数对象和一个定义默认值的对象。加一点糖……

/**
 * Updates an object's properties with other objects' properties. All
 * additional non-falsy arguments will have their properties copied to the
 * destination object, in the order given.
 */
function extend(dest) {
  for (var i = 1, l = arguments.length; i < l; i++) {
    var src = arguments[i]
    if (!src) {
      continue
    }
    for (var property in src) {
      if (src.hasOwnProperty(property)) {
        dest[property] = src[property]
      }
    }
  }
  return dest
}

/**
 * Inherit another function's prototype without invoking the function.
 */
function inherits(child, parent) {
  var F = function() {}
  F.prototype = parent.prototype
  child.prototype = new F()
  child.prototype.constructor = child
  return child
}

...this can be made a bit nicer.

…这可以做得更好一点。

function Field(kwargs) {
  kwargs = extend({
    required: true, widget: null, label: null, initial: null,
    helpText: null, errorMessages: null
  }, kwargs)
  this.required = kwargs.required
  this.label = kwargs.label
  this.initial = kwargs.initial
  // ...and so on...
}

function CharField(kwargs) {
  kwargs = extend({
    maxLength: null, minLength: null
  }, kwargs)
  this.maxLength = kwargs.maxLength
  this.minLength = kwargs.minLength
  Field.call(this, kwargs)
}
inherits(CharField, Field)

What's nice about this method?

这个方法有什么好处?

  • You can omit as many arguments as you like - if you only want to override the value of one argument, you can just provide that argument, instead of having to explicitly pass undefined when, say there are 5 arguments and you only want to customise the last one, as you would have to do with some of the other methods suggested.
  • 你可以省略尽可能多的参数——如果你只想覆盖一个参数的值,你可以提供这一观点,而不是显式地通过定义时,说有5个参数,你只想定制最后一个,你会与其他的一些方法建议。
  • When working with a constructor Function for an object which inherits from another, it's easy to accept any arguments which are required by the constructor of the Object you're inheriting from, as you don't have to name those arguments in your constructor signature, or even provide your own defaults (let the parent Object's constructor do that for you, as seen above when CharField calls Field's constructor).
  • 当处理一个继承自另一个对象的构造函数,很容易接受任何参数的构造函数所需的对象你继承,正如你不需要名字这些参数构造函数签名,甚至提供自己的违约(让父对象的构造函数为你这么做,如上图所示,当CharField调用的构造函数)。
  • Child objects in inheritance hierarchies can customise arguments for their parent constructor as they see fit, enforcing their own default values or ensuring that a certain value will always be used.
  • 继承层次结构中的子对象可以根据父构造函数的需要定制参数,执行自己的默认值,或者确保始终使用某个值。

#8


8  

If you're using defaults extensively, this seems much more readable:

如果你大量使用默认值,这看起来可读性更强:

function usageExemple(a,b,c,d){
    //defaults
    a=defaultValue(a,1);
    b=defaultValue(b,2);
    c=defaultValue(c,4);
    d=defaultValue(d,8);

    var x = a+b+c+d;
    return x;
}

Just declare this function on the global escope.

在全局escope上声明这个函数。

function defaultValue(variable,defaultValue){
    return(typeof variable!=='undefined')?(variable):(defaultValue);
}

Usage pattern fruit = defaultValue(fruit,'Apple');

使用模式果= defaultValue(水果,“苹果”);

*PS you can rename the defaultValue function to a short name, just don't use default it's a reserved word in javascript.

*PS可以将defaultValue函数重命名为短名称,但不要使用默认值,这是javascript中的保留字。

#9


8  

Loose type checking

松散类型检查

Easy to write, but 0, '', false, null and undefined will be converted to default value, which might not be expected outcome.

易于编写,但是0,”,false, null和undefined将被转换为默认值,这可能不是预期的结果。

function myFunc(requiredArg, optionalArg) {
    optionalArg = optionalArg || 'defaultValue';
}

Strict type checking

严格的类型检查

Longer, but covers majority of cases. Only case where it incorrectly assigns default value is when we pass undefined as parameter.

更长,但涵盖了大多数情况。只有当我们将未定义的参数传递给它时,它才会不正确地分配默认值。

function myFunc(requiredArg, optionalArg) {
    optionalArg = typeof optionalArg !== 'undefined' ? optionalArg : 'defaultValue';
}

Checking arguments variable

检查参数变量

Catches all cases but is the most clumsy to write.

抓住所有的情况,但写起来最笨拙。

function myFunc(requiredArg, optionalArg1, optionalArg2) {
    optionalArg1 = arguments.length > 1 ? optionalArg1 : 'defaultValue';
    optionalArg2 = arguments.length > 2 ? optionalArg2 : 'defaultValue';
}

ES6

ES6

Unfortunately this has very poor browser support at the moment

不幸的是,目前这种浏览器的支持非常糟糕

function myFunc(requiredArg, optionalArg = 'defaultValue') {

}

#10


5  

With ES2015/ES6 you can take advantage of Object.assign which can replace $.extend() or _.defaults()

有了ES2015/ES6,你可以充分利用对象。可以替换$.extend()或_.defaults()的赋值

function myFunc(requiredArg, options = {}) {
  const defaults = {
    message: 'Hello',
    color: 'red',
    importance: 1
  };

  const settings = Object.assign({}, defaults, options);

  // do stuff
}

You can also use defaults arguments like this

您还可以使用这样的默认参数

function myFunc(requiredArg, { message: 'Hello', color: 'red', importance: 1 } = {}) {
  // do stuff
}

#11


3  

If you're using the Underscore library (you should, it's an awesome library):

如果您正在使用下划线库(您应该这样做,它是一个很棒的库):

_.defaults(optionalArg, 'defaultValue');

#12


3  

I am used to seeing a few basic variations on handling optional variables. Sometimes, the relaxed versions are useful.

我习惯于看到一些处理可选变量的基本变化。有时,放松的版本是有用的。

function foo(a, b, c) {
  a = a || "default";   // Matches 0, "", null, undefined, NaN, false.
  a || (a = "default"); // Matches 0, "", null, undefined, NaN, false.

  if (b == null) { b = "default"; } // Matches null, undefined.

  if (typeof c === "undefined") { c = "default"; } // Matches undefined.
}

The falsy default used with variable a is, for example, used extensively in Backbone.js.

例如,变量a使用的falsy缺省值在Backbone.js中使用得很广泛。

#13


2  

Landed to this question, searching for default parameters in EcmaScript 2015, thus just mentioning...

回答了这个问题,搜索了EcmaScript 2015的默认参数,所以只提到了……

With ES6 we can do default parameters:

使用ES6,我们可以做默认参数:

function doSomething(optionalParam = "defaultValue"){
    console.log(optionalParam);//not required to check for falsy values
}

doSomething(); //"defaultValue"
doSomething("myvalue"); //"myvalue"

#14


2  

I don't know why @Paul's reply is downvoted, but the validation against null is a good choice. Maybe a more affirmative example will make better sense:

我不知道为什么@Paul的回复被否决,但是对null的验证是一个很好的选择。也许一个更肯定的例子更有意义:

In JavaScript a missed parameter is like a declared variable that is not initialized (just var a1;). And the equality operator converts the undefined to null, so this works great with both value types and objects, and this is how CoffeeScript handles optional parameters.

在JavaScript中,缺失的参数就像未初始化的声明变量(只是var a1;)。等式运算符将undefined转换为null,因此这对于值类型和对象都很有效,这就是CoffeeScript处理可选参数的方式。

function overLoad(p1){
    alert(p1 == null); // Caution, don't use the strict comparison: === won't work.
    alert(typeof p1 === 'undefined');
}

overLoad(); // true, true
overLoad(undefined); // true, true. Yes, undefined is treated as null for equality operator.
overLoad(10); // false, false


function overLoad(p1){
    if (p1 == null) p1 = 'default value goes here...';
    //...
}

Though, there are concerns that for the best semantics is typeof variable === 'undefined' is slightly better. I'm not about to defend this since it's the matter of the underlying API how a function is implemented; it should not interest the API user.

尽管如此,仍然有人担心,对于最好的语义来说,typeof变量== '未定义'稍微好一些。我不打算对此进行辩护,因为实现函数的关键在于底层API;它不应该引起API用户的兴趣。

I should also add that here's the only way to physically make sure any argument were missed, using the in operator which unfortunately won't work with the parameter names so have to pass an index of the arguments.

我还应该补充一点,这是确保任何参数被忽略的唯一方法,使用的操作符很遗憾不能使用参数名,因此必须传递参数的索引。

function foo(a, b) {
    // Both a and b will evaluate to undefined when used in an expression
    alert(a); // undefined
    alert(b); // undefined

    alert("0" in arguments); // true
    alert("1" in arguments); // false
}

foo (undefined);

#15


2  

The test for undefined is unnecessary and isn't as robust as it could be because, as user568458 pointed out, the solution provided fails if null or false is passed. Users of your API might think false or null would force the method to avoid that parameter.

对未定义的测试是不必要的,并且不像可能的那样健壮,因为user568458指出,如果通过null或false,则提供的解决方案失败。API的用户可能认为false或null会迫使方法避免该参数。

function PaulDixonSolution(required, optionalArg){
   optionalArg = (typeof optionalArg === "undefined") ? "defaultValue" : optionalArg;
   console.log(optionalArg);
};
PaulDixonSolution("required");
PaulDixonSolution("required", "provided");
PaulDixonSolution("required", null);
PaulDixonSolution("required", false);

The result is:

其结果是:

defaultValue
provided
null
false

Those last two are potentially bad. Instead try:

最后两种可能是坏的。而不是尝试:

function bulletproof(required, optionalArg){
   optionalArg = optionalArg ? optionalArg : "defaultValue";;
   console.log(optionalArg);
};
bulletproof("required");
bulletproof("required", "provided");
bulletproof("required", null);
bulletproof("required", false);

Which results in:

结果:

defaultValue
provided
defaultValue
defaultValue

The only scenario where this isn't optimal is when you actually have optional parameters that are meant to be booleans or intentional null.

唯一不理想的情况是,当您实际拥有可选参数时,该参数应该是布尔值或故意空值。

#16


2  

I tried some options mentioned in here and performance tested them. At this moment the logicalor seems to be the fastest. Although this is subject of change over time (different JavaScript engine versions).

我尝试了一些在这里提到的选项,并进行了性能测试。此时此刻,逻辑学家似乎是最快的。尽管这是随时间变化的主题(不同的JavaScript引擎版本)。

These are my results (Microsoft Edge 20.10240.16384.0):

这是我的结果(微软Edge 20.10240.16384.0):

Function executed            Operations/sec     Statistics
TypeofFunction('test');          92,169,505     ±1.55%   9% slower
SwitchFuntion('test');            2,904,685     ±2.91%  97% slower
ObjectFunction({param1: 'test'});   924,753     ±1.71%  99% slower
LogicalOrFunction('test');      101,205,173     ±0.92%     fastest
TypeofFunction2('test');         35,636,836     ±0.59%  65% slower

This performance test can be easily replicated on: http://jsperf.com/optional-parameters-typeof-vs-switch/2

这个性能测试可以在http://jsperf.com/optional-parameters-typeof-vs-switch/2上轻松复制

This is the code of the test:

这是测试的代码:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
    Benchmark.prototype.setup = function() {
        function TypeofFunction(param1, optParam1, optParam2, optParam3) {
            optParam1 = (typeof optParam1 === "undefined") ? "Some default" : optParam1;
            optParam2 = (typeof optParam2 === "undefined") ? "Another default" : optParam2;
            optParam3 = (typeof optParam3 === "undefined") ? "Some other default" : optParam3;
        }

        function TypeofFunction2(param1, optParam1, optParam2, optParam3) {
            optParam1 = defaultValue(optParam1, "Some default");
            optParam2 = defaultValue(optParam2, "Another default");
            optParam3 = defaultValue(optParam3, "Some other default");
        }

        function defaultValue(variable, defaultValue) {
            return (typeof variable !== 'undefined') ? (variable) : (defaultValue);
        }

        function SwitchFuntion(param1, optParam1, optParam2, optParam3) {
            switch (arguments.length - 1) { // <-- 1 is number of required arguments
                case 0:
                    optParam1 = 'Some default';
                case 1:
                    optParam2 = 'Another default';
                case 2:
                    optParam3 = 'Some other default';
            }
        }

        function ObjectFunction(args) {
            var defaults = {
                optParam1: 'Some default',
                optParam2: 'Another default',
                optParam3: 'Some other default'
            }
            args = $.extend({}, defaults, args);
        }

        function LogicalOrFunction(param1, optParam1, optParam2, optParam3) {
            optParam1 || (optParam1 = 'Some default');
            optParam2 || (optParam1 = 'Another default');
            optParam3 || (optParam1 = 'Some other default');
        }
    };
</script>

#17


1  

This is what I ended up with:

这就是我最后得出的结论:

function WhoLikesCake(options) {
  options = options || {};
  var defaultOptions = {
    a : options.a || "Huh?",
    b : options.b || "I don't like cake."
  }
  console.log('a: ' + defaultOptions.b + ' - b: ' + defaultOptions.b);

  // Do more stuff here ...
}

Called like this:

像这样:

WhoLikesCake({ b : "I do" });

#18


1  

Folks -

人- - - - - -

After looking at these and other solutions, I tried a number of them out using a snippet of code originally from W3Schools as a base. You can find what works in the following. Each of the items commented out work as well and are that way to allow you to experiment simply by removing individual comments. To be clear, it is the "eyecolor" parameter that is not being defined.

在查看了这些解决方案和其他解决方案之后,我尝试使用W3Schools的一段代码作为基础。您可以在下面找到有效的方法。每个条目都注释掉了工作,这样您就可以通过删除单独的注释进行实验。需要明确的是,“眼镜颜色”参数没有被定义。

function person(firstname, lastname, age, eyecolor)
{
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
this.eyecolor = eyecolor;
// if(null==eyecolor)
//   this.eyecolor = "unknown1";
//if(typeof(eyecolor)==='undefined') 
//   this.eyecolor = "unknown2";
// if(!eyecolor)
//   this.eyecolor = "unknown3";
this.eyecolor = this.eyecolor || "unknown4";
}

var myFather = new person("John", "Doe", 60);
var myMother = new person("Sally", "Rally", 48, "green");

var elem = document.getElementById("demo");
elem.innerHTML = "My father " +
              myFather.firstname + " " +
              myFather.lastname + " is " +
              myFather.age + " with " +
              myFather.eyecolor + " eyes.<br/>" +
              "My mother " +
              myMother.firstname + " " +
              myMother.lastname + " is " +
              myMother.age + " with " +
              myMother.eyecolor + " eyes."; 

#19


1  

function Default(variable, new_value)
{
    if(new_value === undefined) { return (variable === undefined) ? null : variable; }
    return (variable === undefined) ? new_value : variable;
}

var a = 2, b = "hello", c = true, d;

var test = Default(a, 0),
test2 = Default(b, "Hi"),
test3 = Default(c, false),
test4 = Default(d, "Hello world");

window.alert(test + "\n" + test2 + "\n" + test3 + "\n" + test4);

http://jsfiddle.net/mq60hqrf/

http://jsfiddle.net/mq60hqrf/

#20


1  

During a project I noticed I was repeating myself too much with the optional parameters and settings, so I made a class that handles the type checking and assigns a default value which results in neat and readable code. See example and let me know if this works for you.

在一个项目中,我注意到我在可选参数和设置上重复了太多,所以我创建了一个类来处理类型检查并分配一个默认值,从而生成整洁且可读的代码。看看例子,让我知道这是否适合你。

var myCar           = new Car('VW', {gearbox:'automatic', options:['radio', 'airbags 2x']});
var myOtherCar      = new Car('Toyota');

function Car(brand, settings) {
    this.brand      = brand;

    // readable and adjustable code
    settings        = DefaultValue.object(settings, {});
    this.wheels     = DefaultValue.number(settings.wheels, 4);
    this.hasBreaks  = DefaultValue.bool(settings.hasBreaks, true);
    this.gearbox    = DefaultValue.string(settings.gearbox, 'manual');
    this.options    = DefaultValue.array(settings.options, []);

    // instead of doing this the hard way
    settings        = settings || {};
    this.wheels     = (!isNaN(settings.wheels)) ? settings.wheels : 4;
    this.hasBreaks  = (typeof settings.hasBreaks !== 'undefined') ? (settings.hasBreaks === true) : true;
    this.gearbox    = (typeof settings.gearbox === 'string') ? settings.gearbox : 'manual';
    this.options    = (typeof settings.options !== 'undefined' && Array.isArray(settings.options)) ? settings.options : [];
}

Using this class:

使用这个类:

(function(ns) {

    var DefaultValue = {

        object: function(input, defaultValue) {
            if (typeof defaultValue !== 'object') throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined') ? input : defaultValue;
        },

        bool: function(input, defaultValue) {
            if (typeof defaultValue !== 'boolean') throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined') ? (input === true) : defaultValue;
        },

        number: function(input, defaultValue) {
            if (isNaN(defaultValue)) throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined' && !isNaN(input)) ? parseFloat(input) : defaultValue;
        },

        // wrap the input in an array if it is not undefined and not an array, for your convenience
        array: function(input, defaultValue) {
            if (typeof defaultValue === 'undefined') throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined') ? (Array.isArray(input) ? input : [input]) : defaultValue;
        },

        string: function(input, defaultValue) {
            if (typeof defaultValue !== 'string') throw new Error('invalid defaultValue type');
            return (typeof input === 'string') ? input : defaultValue;
        },

    };

    ns.DefaultValue = DefaultValue;

}(this));

#21


1  

Here is my solution. With this you can leave any parameter you want. The order of the optional parameters is not important and you can add custom validation.

这是我的解决方案。有了这个,你可以留下任何你想要的参数。可选参数的顺序并不重要,您可以添加自定义验证。

function YourFunction(optionalArguments) {
            //var scope = this;

            //set the defaults
            var _value1 = 'defaultValue1';
            var _value2 = 'defaultValue2';
            var _value3 = null;
            var _value4 = false;

            //check the optional arguments if they are set to override defaults...
            if (typeof optionalArguments !== 'undefined') {

                if (typeof optionalArguments.param1 !== 'undefined')
                    _value1 = optionalArguments.param1;

                if (typeof optionalArguments.param2 !== 'undefined')
                    _value2 = optionalArguments.param2;

                if (typeof optionalArguments.param3 !== 'undefined')
                    _value3 = optionalArguments.param3;

                if (typeof optionalArguments.param4 !== 'undefined')
                    //use custom parameter validation if needed, in this case for javascript boolean
                   _value4 = (optionalArguments.param4 === true || optionalArguments.param4 === 'true');
            }

            console.log('value summary of function call:');
            console.log('value1: ' + _value1);
            console.log('value2: ' + _value2);
            console.log('value3: ' + _value3);
            console.log('value4: ' + _value4);
            console.log('');
        }


        //call your function in any way you want. You can leave parameters. Order is not important. Here some examples:
        YourFunction({
            param1: 'yourGivenValue1',
            param2: 'yourGivenValue2',
            param3: 'yourGivenValue3',
            param4: true,
        });

        //order is not important
        YourFunction({
            param4: false,
            param1: 'yourGivenValue1',
            param2: 'yourGivenValue2',
        });

        //uses all default values
        YourFunction();

        //keeps value4 false, because not a valid value is given
        YourFunction({
            param4: 'not a valid bool'
        });

#22


1  

  1. arg || 'default' is a great way and works for 90% of cases

    arg || 'default'是一个很好的方法,适用于90%的情况。

  2. It fails when you need to pass values that might be 'falsy'

    当您需要传递可能是“falsy”的值时,它会失败

    • false
    • 0
    • 0
    • NaN
    • ""
    • ”“

    For these cases you will need to be a bit more verbose and check for undefined

    对于这些情况,您需要更详细一些,并检查未定义

  3. Also be careful when you have optional arguments first, you have to be aware of the types of all of your arguments

    还要注意,当您首先有可选参数时,您必须注意所有参数的类型

#23


0  

Correct me if I'm wrong, but this seems like the simplest way (for one argument, anyway):

如果我错了请纠正我,但这似乎是最简单的方法(不管怎样,对于一个论点):

function myFunction(Required,Optional)
{
    if (arguments.length<2) Optional = "Default";
    //Your code
}

#24


0  

Those ones are shorter than the typeof operator version.

这些比运算符类型要短。

function foo(a, b) {
    a !== undefined || (a = 'defaultA');
    if(b === undefined) b = 'defaultB';
    ...
}

#25


0  

In all cases where optionalArg is falsy you will end up with defaultValue.

在所有的情况下,选择阿拉格是假的,你最终会得到默认值。

function myFunc(requiredArg, optionalArg) {
    optionalArg = optionalArg || 'defaultValue';
    console.log(optionalArg);
    // Do stuff
}
myFunc(requiredArg);
myFunc(requiredArg, null);
myFunc(requiredArg, undefined);
myFunc(requiredArg, "");
myFunc(requiredArg, 0);
myFunc(requiredArg, false);

All of the above log defaultValue, because all of 6 are falsy. In case 4, 5, 6 you might not be interested to set optionalArg as defaultValue, but it sets since they are falsy.

上面所有的log defaultValue,因为所有6个都是假的。在情形4,5,6中,您可能对将optionalArg设置为defaultValue不感兴趣,但它会设置,因为它们是假的。

#26


-1  

I suggest you to use ArgueJS this way:

我建议你这样使用论述:

function myFunc(){
  arguments = __({requiredArg: undefined, optionalArg: [undefined: 'defaultValue'})

  //do stuff, using arguments.requiredArg and arguments.optionalArg
  //    to access your arguments

}

You can also replace undefined by the type of the argument you expect to receive, like this:

你也可以用你期望接收到的参数类型来替换未定义的参数,如下所示:

function myFunc(){
  arguments = __({requiredArg: Number, optionalArg: [String: 'defaultValue'})

  //do stuff, using arguments.requiredArg and arguments.optionalArg
  //    to access your arguments

}

#27


-1  

It seems that the safest way - to deal with all \ any falsy types of supplied arguments before deciding to use the default - is to check for the existence\presence of the optional argument in the invoked function.

似乎最安全的方法——在决定使用默认参数之前处理所有的错误类型的参数——是检查被调用函数中可选参数的存在性。

Relying on the arguments object member creation which doesn't even get created if the argument is missing, regardless of the fact that it might be declared, we can write your function like this:

依赖于参数对象成员的创建,即使参数缺失也不会被创建,不管它是否被声明,我们可以这样写你的函数:

  function myFunc(requiredArg, optionalArg){
        optionalArg = 1 in arguments ? optionalArg : 'defaultValue';
  //do stuff
  }

Utilizing this behavior: We can safely check for any missing values on arguments list arbitrarily and explicitly whenever we need to make sure the function gets a certain value required in its procedure.

利用这种行为:当我们需要确保函数在其过程中获得特定的值时,我们可以安全地任意和显式地检查参数列表上的任何缺失值。

In the following demo code we will deliberately put a typeless and valueless undefined as a default value to be able to determine whether it might fail on falsy argument values, such as 0 false etc., or if it behaves as expected.

在下面的演示代码中,我们将故意将一个无类型和无值的未定义值作为默认值,以确定它是否可能在错误的参数值(如0 false等)上失败,或者它是否按预期运行。

function argCheck( arg1, arg2, arg3 ){

       arg1 = 0 in arguments || undefined;
       arg2 = 1 in arguments || false;
       arg3 = 2 in arguments || 0;
   var arg4 = 3 in arguments || null;

   console.log( arg1, arg2, arg3, arg4 ) 
}

Now, checking few falsy argument-values to see if their presence is correctly detected and therefore evaluates to true:

现在,检查一些假的参数值,看看它们的存在是否被正确地检测到,因此评估为true:

argCheck( "", 0, false, null );
>> true true true true

Which means -they didn't fail the recognition of/as expected argument values. Here we have a check with all arguments missing, which according to our algo should acquire their default values even if they're falsy.

也就是说,它们没有忽略对期望参数值的识别。这里我们有一个所有参数缺失的检查,根据algo,它应该获取它们的默认值,即使它们是假的。

argCheck( );
>> undefined false 0 null

As we can see, the arguments arg1, arg2, arg3 and the undeclared arg4, are returning their exact default values, as ordered. Because we've now made sure that it works, we can rewrite the function which will actually be able to use them as in the first example by using: either if or a ternary condition.

如我们所见,参数arg1、arg2、arg3和未声明的arg4按照顺序返回它们的默认值。因为我们已经确定它是可行的,我们可以重写这个函数它实际上可以像第一个例子一样使用它们:if或三元条件。

On functions that have more than one optional argument, - a loop through, might have saved us some bits. But since argument names don't get initialized if their values are not supplied, we cannot access them by names anymore even if we've programmatically written a default value, we can only access them by arguments[index] which useless code readability wise.

对于具有多个可选参数的函数——循环遍历,可能会为我们节省一些比特。但是,既然参数名称没有被初始化,如果它们的值没有被提供,我们就不能再通过名称访问它们了,即使我们以编程的方式编写了一个默认值,我们也只能通过参数[索引]来访问它们,这些参数是无用的代码可读性的。

But aside from this inconvenience, which in certain coding situations might be fully acceptable, there's another unaccounted problem for multiple and arbitrary number of argument defaults. Which may and should be considered a bug, as we can no longer skip arguments, as we once might have been able to, without giving a value, in a syntax such as:

但是,除了这种不便之外(在某些编码情况下可能完全可以接受),还有另一个未解释的问题,即多个或任意数量的参数的缺省值。这可能也应该被认为是一个bug,因为我们再也不能跳过参数了,因为我们曾经可以不给出一个值,使用如下语法:

argCheck("a",,22,{});

because it will throw! Which makes it impossible for us to substitute our argument with a specific falsy type of our desired default value. Which is stupid, since the arguments object is an array-like object and is expected to support this syntax and convention as is, natively or by default!

因为它将抛出!这就使得我们不可能用我们想要的默认值的一种特定的虚假类型来替代我们的论点。这是很愚蠢的,因为arguments对象是一个类数组的对象,并且期望它能够支持这种语法和约定,就像它本身或默认的那样!

Because of this shortsighted decision we can no longer hope to write a function like this:

由于这个短视的决定,我们再也不能指望写出这样的函数:

function argCheck( ) {
    var _default = [undefined, 0, false, null ],
        _arg = arguments;

 for( var x in _default ) {
         x in _arg ? 1 : _arg[x] = _default[x];
        }
    console.log( _arg[0],_arg[1],_arg[2],_arg[3] );
}

in which case, we would be able to write each default value of a desired type in arguments row and be able to at least access them by args.index.

在这种情况下,我们可以在arguments .index中写入所需类型的每个默认值,并且至少可以通过args.index访问它们。

For instance this function call would yield:

例如,这个函数调用将产生:

argCheck();
>>undefined 0 false null

as defined in our default array of arguments values. However the following is still possible:

在参数值的默认数组中定义。但是,仍有可能有下列情况:

argCheck({})
>>Object {  } 0 false null

argCheck({}, [])
>>Object {  } Array [  ] false null

But regretfully not:

但遗憾的是:

 argCheck("a",,,22);
 >>SyntaxError: expected expression, got ','

Which would otherwise be logging:

否则将记录日志:

>>a 0 false 22

but that's in a better world! However - for the original question - the topmost function will do just fine. e.g.:

但那是在一个更好的世界!然而,对于最初的问题,最上面的函数会做得很好。例如:

function argCheck( arg, opt ) {
         1 in arguments ? 1 : opt = "default";
         console.log( arg, opt );
}

p.s.: sorry for not preserving the types of chosen defaults in my argument inputs while writing them.

注。:抱歉,在编写参数输入时没有保存所选择的默认值类型。

#28


-1  

Some code IntelliSense tools, in particular the WebStorm IDE and perhaps jshint, give warnings when you call a function with fewer arguments than declared:

一些代码智能感知工具,特别是WebStorm IDE,可能还有jshint,当你调用一个参数少于声明的函数时,会给出警告:

function foo(a, b) {
    if (typeof b === 'undefined') {
        b = 5;
    }
    …
}

foo(1); /* Warning */

You can instead do:

你可以做的:

function foo(a /*, b */) {
    var b = arguments.length > 1 ? arguments[1] : 2;
    …
}

foo(1);

Note that the b argument is declared in a comment for clarity.

注意,b参数是在注释中声明的,以保持清晰。

#29


-2  

function foo(requiredArg){
  if(arguments.length>1) var optionalArg = arguments[1];
}