在Javascript中伪造函数重载的最好方法是什么?
我知道在Javascript中不可能像在其他语言中那样重载函数。 如果我需要一个函数有两个使用foo(x)和foo(x,y,z),这是最好的/首选的方式:
一开始就用不同的名字 使用可选参数,如y = y || 'default' 使用参数数量 检查参数类型 还是如何?
在Javascript中伪造函数重载的最好方法是什么?
我知道在Javascript中不可能像在其他语言中那样重载函数。 如果我需要一个函数有两个使用foo(x)和foo(x,y,z),这是最好的/首选的方式:
一开始就用不同的名字 使用可选参数,如y = y || 'default' 使用参数数量 检查参数类型 还是如何?
当前回答
正确答案是JAVASCRIPT中没有重载。
检查/切换内部的功能不是过载。
超载的概念: 在某些编程语言中,函数重载或方法重载是用不同的实现创建多个同名方法的能力。对重载函数的调用将运行该函数的特定实现,适用于调用的上下文,允许一个函数调用根据上下文执行不同的任务。
例如,doTask()和doTask(object O)是重载方法。要调用后者,必须将对象作为参数传递,而前者不需要参数,并且使用空参数字段调用。一个常见的错误是将默认值赋给第二个方法中的对象,这将导致一个模糊的调用错误,因为编译器不知道使用两个方法中的哪一个。
https://en.wikipedia.org/wiki/Function_overloading
所有建议的实现都很棒,但说实话,JavaScript没有原生实现。
其他回答
你现在可以在ECMAScript 2018中进行函数重载,而无需填充,检查var长度/类型等,只需使用扩展语法。
function foo(var1, var2, opts){ // set default values for parameters const defaultOpts = { a: [1,2,3], b: true, c: 0.3289, d: "str", } // merge default and passed-in parameters // defaultOpts must go first! const mergedOpts = {...defaultOpts, ...opts}; // you can now refer to parameters like b as mergedOpts.b, // or just assign mergedOpts.b to b console.log(mergedOpts.a); console.log(mergedOpts.b); console.log(mergedOpts.c); console.log(mergedOpts.d); } // the parameters you passed in override the default ones // all JS types are supported: primitives, objects, arrays, functions, etc. let var1, var2="random var"; foo(var1, var2, {a: [1,2], d: "differentString"}); // parameter values inside foo: //a: [1,2] //b: true //c: 0.3289 //d: "differentString"
什么是扩展语法?
ECMAScript提案的Rest/Spread Properties(阶段4)将扩展属性添加到对象字面量中。它将自己的可枚举属性从提供的对象复制到新对象上。 更多关于mdn
注意:对象字面量中的扩展语法在Edge和IE中不起作用,这是一个实验特性。查看浏览器兼容性
JavaScript中没有真正的函数重载,因为它允许传递任意数量的任意类型的参数。你必须检查函数内部传递了多少参数以及它们的类型。
我经常这样做:
C#:
public string CatStrings(string p1) {return p1;}
public string CatStrings(string p1, int p2) {return p1+p2.ToString();}
public string CatStrings(string p1, int p2, bool p3) {return p1+p2.ToString()+p3.ToString();}
CatStrings("one"); // result = one
CatStrings("one",2); // result = one2
CatStrings("one",2,true); // result = one2true
JavaScript相当于:
function CatStrings(p1, p2, p3)
{
var s = p1;
if(typeof p2 !== "undefined") {s += p2;}
if(typeof p3 !== "undefined") {s += p3;}
return s;
};
CatStrings("one"); // result = one
CatStrings("one",2); // result = one2
CatStrings("one",2,true); // result = one2true
This particular example is actually more elegant in javascript than C#. Parameters which are not specified are 'undefined' in javascript, which evaluates to false in an if statement. However, the function definition does not convey the information that p2 and p3 are optional. If you need a lot of overloading, jQuery has decided to use an object as the parameter, for example, jQuery.ajax(options). I agree with them that this is the most powerful and clearly documentable approach to overloading, but I rarely need more than one or two quick optional parameters.
编辑:根据Ian的建议更改IF测试
有两种方法可以更好地解决这个问题:
如果您希望保留很大的灵活性,则传递一个字典(关联数组) 将一个对象作为参数,并使用基于原型的继承来增加灵活性。
最好的方法取决于函数和参数。你的每个选择在不同的情况下都是一个好主意。我通常按照以下顺序尝试这些方法,直到其中一个有效为止:
Using optional arguments like y = y || 'default'. This is convenient if you can do it, but it may not always work practically, e.g. when 0/null/undefined would be a valid argument. Using number of arguments. Similar to the last option but may work when #1 doesn't work. Checking types of arguments. This can work in some cases where the number of arguments is the same. If you can't reliably determine the types, you may need to use different names. Using different names in the first place. You may need to do this if the other options won't work, aren't practical, or for consistency with other related functions.