在Javascript中伪造函数重载的最好方法是什么?

我知道在Javascript中不可能像在其他语言中那样重载函数。 如果我需要一个函数有两个使用foo(x)和foo(x,y,z),这是最好的/首选的方式:

一开始就用不同的名字 使用可选参数,如y = y || 'default' 使用参数数量 检查参数类型 还是如何?


当前回答

所以我真的很喜欢这种做事的方式,这是我在javascript忍者的秘密中发现的

function addMethod(object,name,fn){
  var old = object[name];
  object[name] = function(){
    if (fn.length == arguments.length){
      return fn.apply(this,arguments);
    } else if(typeof old == 'function'){
        return old.apply(this,arguments);
    }
  }
}

然后使用addMethod将重载函数添加到任何对象。对我来说,这段代码中的主要困惑是fn的使用。Length ==参数。长度,这是因为fn。长度是预期参数的数量,而参数。长度是函数实际调用的参数的数量。匿名函数没有参数的原因是你可以在javascript中传入任意数量的参数,并且语言是宽容的。

我喜欢这个,因为你可以在任何地方使用它-只需创建这个函数,并在任何你想要的代码库中简单地使用这个方法。

它还避免了一个大得离谱的if/switch语句,如果您开始编写复杂的代码,它将变得难以阅读(接受的答案将导致这种结果)。

在缺点方面,我想代码一开始有点晦涩……但我不确定其他人?

其他回答

你现在可以在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中不起作用,这是一个实验特性。查看浏览器兼容性

我经常这样做:

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测试

我正在做一个库,提供类的代码功能,Javascript,目前它支持构造函数,继承,方法重载参数的数量和参数的类型,混合,静态属性和单例。

请参阅使用该库的方法重载示例:

eutsiv.define('My.Class', {
    constructor: function() {
        this.y = 2;
    },
    x: 3,
    sum: function() {
        return this.x + this.y;
    },
    overloads: {
        value: [
            function() { return this.x + ', ' + this.y },
            function(p1) { this.x = p1; },
            function(p1, p2) { this.x = p1; this.y = p2; }  // will set x and y
        ]
    }
});

var test = new My.Class({ x: 5 });   // create the object
test.value();                        // will return '5, 2'
test.sum();                          // will return 7
test.value(13);                      // will set x to 13
test.value();                        // will return '13, 2'
test.sum();                          // will return 15
test.value(10, 20);                  // will set x to 10 and y to 20
test.value();                        // will return '10, 20'
test.sum();                          // will return 30

欢迎任何反馈,bug修复,文档和测试改进!

https://github.com/eutsiv/eutsiv.js

Javascript中的函数重载:

函数重载是一种编程语言用不同的实现创建多个同名函数的能力。当重载函数被调用时,它将运行该函数的特定实现,以适应调用的上下文。这个上下文通常是接收参数的数量,它允许一个函数调用根据上下文表现不同。

Javascript没有内置的函数重载。然而,这种行为可以通过许多方式来模仿。这里有一个简单方便的例子:

函数sayHi(a, b) { Console.log ('hi there ' + a); 如果(b) {console.log('and ' + b)} //如果参数存在,则执行该块 } sayHi(“弗兰克”,“威廉”);

在你不知道你将得到多少参数的情况下,你可以使用rest操作符,即三点....它将把剩余的参数转换为一个数组。但是要注意浏览器的兼容性。这里有一个例子:

函数foo (a,…b) { console.log (b); } foo(1、2、3、4); foo(1、2);

不是每个人都知道可以在函数签名中直接进行解构赋值。

得益于此,您可以轻松地定义非常灵活的方法签名,恕我直言,这比Java方法重载更优越。

例子:

const myFunction = (({a, b, c}) => {
    console.log(a, b, c);
});

myFunction({a: 1, b: 2});
myFunction({a: 1, b: 2, c: 3});

您甚至不需要考虑参数的顺序,并且调用语句和目标方法签名之间具有命名一致性。

你也可以指定默认值:

const myFunction = (({a = 1, b = 2, c} = {}) => {
    console.log(a, b, c);
});