Javascript 中的参数重载有多个方面:
可变参数- 您可以传递不同的参数集(类型和数量),函数的行为方式将与传递给它的参数相匹配。
 
默认参数- 如果未传递参数,您可以为其定义默认值。
 
命名参数- 参数顺序变得无关紧要,您只需命名要传递给函数的参数即可。
 
下面是关于这些类型的参数处理中的每一个的部分。
变量参数
由于 javascript 没有对参数或所需参数数量进行类型检查,因此您可以myFunc()通过检查参数的类型、存在或数量来适应传递给它的参数的一种实现。
jQuery 一直这样做。您可以将一些参数设为可选,或者您可以根据传递给它的参数在您的函数中进行分支。
在实现这些类型的重载时,您可以使用几种不同的技术:
- 您可以通过检查声明的参数名称值是否为 来检查任何给定参数的存在
undefined。 
- 您可以使用 来检查总量或参数
arguments.length。 
- 您可以检查任何给定参数的类型。
 
- 对于可变数量的参数,您可以使用
arguments伪数组访问任何给定的参数arguments[i]。 
这里有些例子:
我们来看看jQuery的obj.data()方法。它支持四种不同的使用形式:
obj.data("key");
obj.data("key", value);
obj.data();
obj.data(object);
每个都会触发不同的行为,如果不使用这种动态形式的重载,则需要四个独立的函数。
以下是人们如何用英语区分所有这些选项,然后我会将它们全部组合在代码中:
// get the data element associated with a particular key value
obj.data("key");
如果传递给的第一个参数.data()是字符串而第二个参数是undefined,则调用者必须使用这种形式。
// set the value associated with a particular key
obj.data("key", value);
如果第二个参数不是未定义的,则设置特定键的值。
// get all keys/values
obj.data();
如果没有传递参数,则返回返回对象中的所有键/值。
// set all keys/values from the passed in object
obj.data(object);
如果第一个参数的类型是普通对象,则设置该对象的所有键/值。
以下是将所有这些组合到一组 javascript 逻辑中的方法:
 // method declaration for .data()
 data: function(key, value) {
     if (arguments.length === 0) {
         // .data()
         // no args passed, return all keys/values in an object
     } else if (typeof key === "string") {
         // first arg is a string, look at type of second arg
         if (typeof value !== "undefined") {
             // .data("key", value)
             // set the value for a particular key
         } else {
             // .data("key")
             // retrieve a value for a key
         }
     } else if (typeof key === "object") {
         // .data(object)
         // set all key/value pairs from this object
     } else {
         // unsupported arguments passed
     }
 },
此技术的关键是确保您要接受的所有参数形式都是唯一可识别的,并且永远不会混淆调用者正在使用哪种形式。这通常需要适当地对参数进行排序,并确保参数的类型和位置具有足够的唯一性,以便您始终可以判断正在使用哪种形式。
例如,如果您有一个接受三个字符串参数的函数:
obj.query("firstArg", "secondArg", "thirdArg");
您可以轻松地将第三个参数设为可选,并且可以轻松检测到该条件,但您不能只将第二个参数设为可选,因为您无法判断调用者要传递的参数是哪一个,因为无法确定第二个参数是否为参数是第二个参数,或者第二个参数被省略,所以第二个参数的位置实际上是第三个参数:
obj.query("firstArg", "secondArg");
obj.query("firstArg", "thirdArg");
由于所有三个参数都是相同的类型,因此您无法区分不同参数之间的区别,因此您不知道调用者的意图。使用这种调用方式,只有第三个参数可以是可选的。如果您想省略第二个参数,则必须将其作为null(或其他一些可检测值)传递,您的代码将检测到:
obj.query("firstArg", null, "thirdArg");
这是可选参数的 jQuery 示例。两个参数都是可选的,如果没有传递则采用默认值:
clone: function( dataAndEvents, deepDataAndEvents ) {
    dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
    deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
    return this.map( function () {
        return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
    });
},
这是一个 jQuery 示例,其中可以缺少参数或三种不同类型中的任何一种,它为您提供四种不同的重载:
html: function( value ) {
    if ( value === undefined ) {
        return this[0] && this[0].nodeType === 1 ?
            this[0].innerHTML.replace(rinlinejQuery, "") :
            null;
    // See if we can take a shortcut and just use innerHTML
    } else if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
        (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
        !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
        value = value.replace(rxhtmlTag, "<$1></$2>");
        try {
            for ( var i = 0, l = this.length; i < l; i++ ) {
                // Remove element nodes and prevent memory leaks
                if ( this[i].nodeType === 1 ) {
                    jQuery.cleanData( this[i].getElementsByTagName("*") );
                    this[i].innerHTML = value;
                }
            }
        // If using innerHTML throws an exception, use the fallback method
        } catch(e) {
            this.empty().append( value );
        }
    } else if ( jQuery.isFunction( value ) ) {
        this.each(function(i){
            var self = jQuery( this );
            self.html( value.call(this, i, self.html()) );
        });
    } else {
        this.empty().append( value );
    }
    return this;
},
命名参数
其他语言(如 Python)允许传递命名参数作为仅传递一些参数并使参数独立于它们传入的顺序的一种方式。Javascript 不直接支持命名参数的特性。一种常用的设计模式是传递属性/值的映射。这可以通过传递具有属性和值的对象来完成,或者在 ES6 及更高版本中,您实际上可以传递 Map 对象本身。
这是一个简单的 ES5 示例:
jQuery$.ajax()接受一种使用形式,您只需将单个参数传递给它,该参数是具有属性和值的常规 Javascript 对象。传递给它的属性决定了传递给 ajax 调用的参数/选项。有些可能是必需的,许多是可选的。由于它们是对象的属性,因此没有特定的顺序。事实上,可以在该对象上传递 30 多种不同的属性,只需要一个(url)。
下面是一个例子:
$.ajax({url: "http://www.example.com/somepath", data: myArgs, dataType: "json"}).then(function(result) {
    // process result here
});
在$.ajax()实现内部,它可以查询传入对象上传递的属性,并将这些属性用作命名参数。这可以通过使用for (prop in obj)或通过将所有属性放入数组Object.keys(obj)然后迭代该数组来完成。
当有大量参数和/或许多参数是可选的时,这种技术在 Javascript 中非常常用。注意:这给实现函数带来了责任,以确保存在最小的有效参数集,并在传递的参数不足时向调用者提供一些调试反馈(可能通过抛出带有有用错误消息的异常) .
在 ES6 环境中,可以使用解构为上述传递的对象创建默认属性/值。本参考文章对此进行了更详细的讨论。
这是那篇文章中的一个例子:
function selectEntries({ start=0, end=-1, step=1 } = {}) {
    ···
};
然后,您可以像以下任何一个一样调用它:
selectEntries({start: 5});
selectEntries({start: 5, end: 10});
selectEntries({start: 5, end: 10, step: 2});
selectEntries({step: 3});
selectEntries();
您未在函数调用中列出的参数将从函数声明中获取它们的默认值。
这将创建默认属性和值start,end并step传递到一个对象的属性selectEntries()的功能。
函数参数的默认值
在 ES6 中,Javascript 为参数的默认值添加了内置语言支持。
例如:
function multiply(a, b = 1) {
  return a*b;
}
multiply(5); // 5
在 MDN 上进一步描述可以在此处使用的方式。