在Javascript中伪造函数重载的最好方法是什么?
我知道在Javascript中不可能像在其他语言中那样重载函数。 如果我需要一个函数有两个使用foo(x)和foo(x,y,z),这是最好的/首选的方式:
一开始就用不同的名字 使用可选参数,如y = y || 'default' 使用参数数量 检查参数类型 还是如何?
在Javascript中伪造函数重载的最好方法是什么?
我知道在Javascript中不可能像在其他语言中那样重载函数。 如果我需要一个函数有两个使用foo(x)和foo(x,y,z),这是最好的/首选的方式:
一开始就用不同的名字 使用可选参数,如y = y || 'default' 使用参数数量 检查参数类型 还是如何?
当前回答
JavaScript是一种无类型语言,我认为只有在参数数量方面重载方法/函数才有意义。因此,我建议检查参数是否已经定义:
myFunction = function(a, b, c) {
if (b === undefined && c === undefined ){
// do x...
}
else {
// do y...
}
};
其他回答
在javascript中没有办法实现函数重载。 因此,我推荐使用下面的by typeof()方法而不是 多重功能伪造过载。
function multiTypeFunc(param)
{
if(typeof param == 'string') {
alert("I got a string type parameter!!");
}else if(typeof param == 'number') {
alert("I got a number type parameter!!");
}else if(typeof param == 'boolean') {
alert("I got a boolean type parameter!!");
}else if(typeof param == 'object') {
alert("I got a object type parameter!!");
}else{
alert("error : the parameter is undefined or null!!");
}
}
好运!
用形参重载函数的最好方法不是检查实参长度或类型;检查类型只会让你的代码变慢,你可以享受数组、空值、对象等的乐趣。
大多数开发人员所做的是将一个对象作为方法的最后一个参数。这个物体可以装任何东西。
function foo(a, b, opts) {
// ...
if (opts['test']) { } //if test param exists, do something..
}
foo(1, 2, {"method":"add"});
foo(3, 4, {"test":"equals", "bar":"tree"});
然后你可以在你的方法中任意处理它。[开关,if-else,等等]
介绍
到目前为止,阅读这么多答案会让任何人感到头疼。任何试图了解这个概念的人都需要知道以下先决条件。
函数重载定义,函数长度属性,函数参数属性
最简单形式的函数重载意味着函数根据传递给它的参数数量执行不同的任务。值得注意的是TASK1, TASK2和TASK3在下面突出显示,它们是根据传递给同一个函数fooYo的参数数量来执行的。
// if we have a function defined below
function fooYo(){
// do something here
}
// on invoking fooYo with different number of arguments it should be capable to do different things
fooYo(); // does TASK1
fooYo('sagar'); // does TASK2
fooYo('sagar','munjal'); // does TAKS3
请注意 JS不提供内置的函数重载功能。
替代
John E Resig (JS的创建者)指出了一种替代方法,它使用上述先决条件来实现函数重载的能力。
下面的代码通过使用if-else或switch语句使用了一种简单但简单的方法。
计算参数长度属性。 不同的值导致调用不同的函数。
Var ninja = { function() { 切换(arguments.length) { 例0: /*做某事*/ 打破; 案例1: /* do something else */ 打破; 案例2: /*做其他事情*/ 打破; //等等… } } }
另一种技术更加简洁和动态。这项技术的亮点是addMethod泛型函数。
我们定义了一个addMethod函数,它用于向一个对象添加不同的函数,这些函数具有相同的名称但不同的功能。 下面的addMethod函数接受三个参数:对象名称object,函数名称name和我们想要调用的函数fn。 在addMethod定义中,var old存储了对前一个函数的引用,该函数通过闭包(一个保护气泡)的帮助存储。
函数addMethod(对象,名称,fn) { Var old =对象[name]; 对象[name] = function(){ 如果(fn)。Length == arguments.length) 返回fn。应用(这个参数) Else if (typeof old == 'function') 返回旧。应用(这个参数); }; };
使用调试器来理解代码流。 下面的addMethod添加了三个函数,当使用ninja.whatever(x)调用时,参数x的数量可以是任何东西,即空白或一个或多个调用不同的函数定义,同时使用addMethod函数。
Var ninja = {}; 调试器; addMethod(ninja,'whatever',function(){console.log("我是那个提供了零参数的人")}); addMethod(ninja,'whatever',function(a){console.log("我是提供了一个参数的人")}); addMethod(ninja,'whatever',function(a,b){console.log("我是一个提供了两个参数的人")}); ninja.whatever (); ninja.whatever(1、2); ninja.whatever (3);
下面是一种使用参数类型允许真正的方法重载的方法,如下所示:
Func(new Point());
Func(new Dimension());
Func(new Dimension(), new Point());
Func(0, 0, 0, 0);
Edit(2018):自2011年编写以来,直接方法调用的速度大大提高,而重载方法的速度却没有提高。
这不是我推荐的方法,但思考如何解决这类问题是一个值得思考的练习。
这里是不同方法的基准测试- https://jsperf.com/function-overloading。它显示函数重载(考虑到类型)可以在谷歌Chrome的V8 16.0(测试版)慢大约13倍。
除了传递一个对象(例如{x: 0, y: 0}),还可以在适当的时候采用C方法,相应地命名方法。例如,vector . addvector (vector), vector . addvector。AddIntegers(x, y, z,…)和Vector.AddArray(integerArray)。您可以查看C库,例如OpenGL,以获得命名灵感。
编辑:我已经添加了一个基准,用于传递一个对象,并使用arg和arg. hasownproperty ('param')中的'param'测试对象,函数重载比传递一个对象和检查属性快得多(至少在这个基准测试中)。
From a design perspective, function overloading is only valid or logical if the overloaded parameters correspond to the same action. So it stands to reason that there ought to be an underlying method that is only concerned with specific details, otherwise that may indicate inappropriate design choices. So one could also resolve the use of function overloading by converting data to a respective object. Of course one must consider the scope of the problem as there's no need in making elaborate designs if your intention is just to print a name, but for the design of frameworks and libraries such thought is justified.
我的例子来自一个矩形实现——因此提到了维和点。也许Rectangle可以向Dimension and Point原型添加一个GetRectangle()方法,然后对函数重载问题进行排序。那原语呢?好的,我们有参数length,这现在是一个有效的测试,因为对象有一个GetRectangle()方法。
function Dimension() {}
function Point() {}
var Util = {};
Util.Redirect = function (args, func) {
'use strict';
var REDIRECT_ARGUMENT_COUNT = 2;
if(arguments.length - REDIRECT_ARGUMENT_COUNT !== args.length) {
return null;
}
for(var i = REDIRECT_ARGUMENT_COUNT; i < arguments.length; ++i) {
var argsIndex = i-REDIRECT_ARGUMENT_COUNT;
var currentArgument = args[argsIndex];
var currentType = arguments[i];
if(typeof(currentType) === 'object') {
currentType = currentType.constructor;
}
if(typeof(currentType) === 'number') {
currentType = 'number';
}
if(typeof(currentType) === 'string' && currentType === '') {
currentType = 'string';
}
if(typeof(currentType) === 'function') {
if(!(currentArgument instanceof currentType)) {
return null;
}
} else {
if(typeof(currentArgument) !== currentType) {
return null;
}
}
}
return [func.apply(this, args)];
}
function FuncPoint(point) {}
function FuncDimension(dimension) {}
function FuncDimensionPoint(dimension, point) {}
function FuncXYWidthHeight(x, y, width, height) { }
function Func() {
Util.Redirect(arguments, FuncPoint, Point);
Util.Redirect(arguments, FuncDimension, Dimension);
Util.Redirect(arguments, FuncDimensionPoint, Dimension, Point);
Util.Redirect(arguments, FuncXYWidthHeight, 0, 0, 0, 0);
}
Func(new Point());
Func(new Dimension());
Func(new Dimension(), new Point());
Func(0, 0, 0, 0);
看看这个。它很酷。 http://ejohn.org/blog/javascript-method-overloading/ 技巧Javascript,让你做这样的调用:
var users = new Users();
users.find(); // Finds all
users.find("John"); // Finds users by name
users.find("John", "Resig"); // Finds users by first and last name