Javascript中的方法重载
Posted
技术标签:
【中文标题】Javascript中的方法重载【英文标题】:Method overloading in Javascript 【发布时间】:2012-09-23 13:26:47 【问题描述】:我在我的 javascript 代码中使用如下方法重载。
function somefunction()
//1st function
function somefunction(a)
//2nd function
function somefunction(a,b)
//3rd function
somefunction(); // function call goes here
我不明白的是,如果我调用 somefunction()
javascript 应该调用 第一个函数,但问题是 javascript 实际上调用了第三个函数。这是为什么?如何调用第一个和第二个函数?这是什么原因?是否有适当的方法在 Javascript 中实现方法重载?行业标准是什么?
【问题讨论】:
你不能在 JavaScript 中做到这一点。定义一个函数,然后在其中有分支来涵盖各种参数组合。 那么如何在 javascript 中使用面向对象的实践? Javascript 确实可以处理未传递的变量。因此,只需创建一个接收 (a, b) 的函数并读取输入以确定您的执行路线。 @Dasun 哪些对象装饰做法? @Šime Vidas 方法重载 【参考方案1】:JavaScript 不支持方法重载(如在 Java 中或类似的),您的第三个函数会覆盖之前的声明。
相反,它通过arguments
object 支持可变参数。你可以这样做
function somefunction(a, b)
if (arguments.length == 0) // a, b are undefined
// 1st body
else if (arguments.length == 1) // b is undefined
// 2nd body
else if (arguments.length == 2) // both have values
// 3rd body
// else throw new SyntaxError?
您也可以只检查typeof a == "undefined"
等,这将允许调用somefunction(undefined)
,其中arguments.length
是1
。这可能允许使用各种参数更轻松地调用,例如当您有可能为空的变量时。
【讨论】:
如果只有一个参数传递给函数调用,我怎么知道它是哪个参数..?喜欢somefunction(something);
@RohitSharma 如果只有一个,那就是第一个。 JavaScript 不支持命名参数,重要的是顺序。
那么,我怎样才能使第一个参数可选..?
@RohitSharma 你不能。当然可以拨打someFunction(undefined, someValue)
。
只是为了清关...! :) 但是,jQuery 的 on()
方法如何适用于不同类型的参数使用。像.on('event','selector',callback)
或.on('event',callback)
一样,我们不会在那里为可选参数传递 undefined ......!【参考方案2】:
JS 会将undefined
传递给任何未提供的参数。如果你想要重载之类的东西,你需要做类似下面的代码:
function someFunction(a, b)
if (typeof a === 'undefined')
// Do the 0-parameter logic
else if (typeof b === 'undefined')
// Do the 1-parameter logic
else
// Do the 2-parameter logic
【讨论】:
【参考方案3】:您只是在每次新声明时擦除变量somefunction
。
这相当于
window.somefunction = function(...
window.somefunction = function(...
window.somefunction = function(...
Javascript 不提供方法重载。
正确的方法是:
定义第三个函数并测试定义了哪些参数 只传递一个包含参数的对象(实际上并没有什么不同,但更简洁)【讨论】:
这个答案是错误的。函数 somefunc() ;与 var somefunc = function() ; 进行比较作为证明,如果您稍后声明 function anotherFunction() window.somefunc(); 【参考方案4】:您不能在 JavaScript 中重载方法。在 javascript 中,函数存储在变量中。全局变量存储在窗口对象上。每个对象只能有一个同名的属性(独占键哈希)。
您可以做的是定义具有最多参数的定义并检查传入了多少。
function Test(a, b, c)
if(typeof a == 'undefined')
a = 1;
if(typeof b == 'undefined')
b = "hi";
if(typeof c == 'undefined')
c = Date.Now;
现在,如果我调用 Test(),它的行为就像我调用了 Test(1, "hi", Date.Now)
【讨论】:
【参考方案5】:在 JavaScript 中没有真正的函数重载,因为它允许传递任意数量的任意类型的参数。最好的做法是制作一个函数 喜欢: 我的函数(选择)
// with opt = 'arg1':'a1','arg2':2, etc, then check your opt inside of the function
【讨论】:
【参考方案6】:我试图为here 描述的这个问题开发一个优雅的解决方案。你可以找到演示here。用法如下:
var out = def(
'int': function(a)
alert('Here is int '+a);
,
'float': function(a)
alert('Here is float '+a);
,
'string': function(a)
alert('Here is string '+a);
,
'int,string': function(a, b)
alert('Here is an int '+a+' and a string '+b);
,
'default': function(obj)
alert('Here is some other value '+ obj);
);
out('ten');
out(1);
out(2, 'robot');
out(2.5);
out(true);
用于实现此目的的方法:
var def = function(functions, parent)
return function()
var types = [];
var args = [];
eachArg(arguments, function(i, elem)
args.push(elem);
types.push(whatis(elem));
);
if(functions.hasOwnProperty(types.join()))
return functions[types.join()].apply(parent, args);
else
if (typeof functions === 'function')
return functions.apply(parent, args);
if (functions.hasOwnProperty('default'))
return functions['default'].apply(parent, args);
;
;
var eachArg = function(args, fn)
var i = 0;
while (args.hasOwnProperty(i))
if(fn !== undefined)
fn(i, args[i]);
i++;
return i-1;
;
var whatis = function(val)
if(val === undefined)
return 'undefined';
if(val === null)
return 'null';
var type = typeof val;
if(type === 'object')
if(val.hasOwnProperty('length') && val.hasOwnProperty('push'))
return 'array';
if(val.hasOwnProperty('getDate') && val.hasOwnProperty('toLocaleTimeString'))
return 'date';
if(val.hasOwnProperty('toExponential'))
type = 'number';
if(val.hasOwnProperty('substring') && val.hasOwnProperty('length'))
return 'string';
if(type === 'number')
if(val.toString().indexOf('.') > 0)
return 'float';
else
return 'int';
return type;
;
【讨论】:
【参考方案7】:我不明白的是,如果我调用 somefunction() javascript 应该调用第一个函数,但问题是 javascript 实际上调用了第三个函数。
这是预期的行为。
为什么会这样?
问题在于 JavaScript 本身并不支持方法重载。因此,如果它看到/解析两个或多个同名函数,它只会考虑最后定义的函数并覆盖之前的函数。
这是为什么呢?如何调用第一个和第二个函数?这是什么原因?
我认为适合大多数情况的一种方式如下 -
假设你有方法
function foo(x)
您可以定义一个新方法
,而不是重载方法这在javascript中是不可能的fooNew(x,y,z)
然后修改第一个函数如下-
function foo(x)
if(arguments.length==2)
return fooNew(arguments[0], arguments[1]);
如果您有许多这样的重载方法,请考虑使用switch
而不仅仅是if-else
语句。
是否有适当的方法来进行方法重载?行业标准是什么?
在 javascript 中没有这样的标准或更成熟的方法来进行方法重载。应该做最适合他们的编程设计的事情。 我想说简单地打开参数长度并检查类型是否未定义就足够了。
【讨论】:
【参考方案8】:arguments 对象用于创建类似概念的方法重载。
参数是一种特殊类型的对象,仅在函数执行上下文中可用。
arguments.length属性用于标识传入函数的参数个数。
您可以更好地利用第一类函数来创建假方法重载。完整的概念在我自己的网站上进行了解释:Overload Functions in JavaScript
【讨论】:
您好,请记得在分享链接时披露您与您网站的连接! Tyler 我已经在我的博文中解释了方法重载的概念。这就是为什么添加我的博客链接 是的,但您需要在您的回答中指出该网站是您的。【参考方案9】:JavaScript 不直接支持方法重载。 这是一个示例,您可以如何实现与它非常相似的目标,如下所示:
function overloadMethod(object, name, fn)
if(!object._overload)
object._overload = ;
if(!object._overload[name])
object._overload[name] = ;
if(!object._overload[name][fn.length])
object._overload[name][fn.length] = fn;
object[name] = function()
if(this._overload[name][arguments.length])
return this._overload[name][arguments.length].apply(this, arguments);
;
function Students()
overloadMethod(this, "find", function()
// Find a student by name
);
overloadMethod(this, "find", function(first, last)
// Find a student by first and last name
);
var students = new Students();
students.find(); // Finds all
students.find("Rahul"); // Finds students by name
students.find("Rahul", "Mhatre"); // Finds users by first and last name
来源:source
【讨论】:
【参考方案10】:如果你使用类,你会创建两个不同的类,它们具有相同的方法和不同的参数。然后,您可以使用扩展运算符和依赖注入来模拟重载行为。
class Foo
method()
console.log('hello from method foo')
class Bar
method(name)
console.log(`hello from method bar. Name is $name`)
function MimicOverload(obj, options)
obj.method(...options)
const obj1 = new Foo()
const obj2 = new Bar()
MimicOverload(obj1,[])
MimicOverload(obj2,['overloaded'])
【讨论】:
【参考方案11】:I tinkered with this 并且能够轻松地针对自定义类进行这项工作。
let overloadTest = overload(
[String], function(value)
console.log('we got a string', value);
,
[Number], function(value)
console.log('we got a number', value);
,
[String, Number], function(s, n)
console.log('we got a string AND a number', s, n);
[MyCustomClass], function(value)
console.log('we got a MyCustomClass instance', value);
);
有了这个overload
实现:
function overload(...overloads)
const f = function(...args)
let constructorArray = args.map(arg => arg.constructor);
let implIndex = f.overloads.findIndex(sig =>
return constructorArray.length === sig.length &&
constructorArray.every((o,i) => o === sig[i])
;
) + 1;
if (implIndex > 0 && typeof(f.overloads[implIndex]) === 'function')
return f.overloads[implIndex].apply(, args);
else
const message = "There is no implementation that matches the provided arguments.";
console.error(message, constructorArray);
throw Error(message);
;
f.overloads = overloads;
return f;
;
这还不适用于实例方法。但是,它可以扩展。
此外,参数列表直接引用构造函数(而不是字符串),这意味着您可以根据需要扩展额外的验证 - 例如,确保每个参数类型实际上是 @987654325 处的函数/构造函数@ 时间。您还可以想象创建一个执行 DI 的 overload()
版本。
【讨论】:
【参考方案12】:我认为这不能被认为是方法重载,但是使用一个函数来不同的参数组合是一种替代方法。函数的参数必须是一个对象。
function something(obj)
if(obj.a != undefined)
return a*a;
if((obj.b != undefined)&&(obj.c != undefined))
return b*c;
【讨论】:
以上是关于Javascript中的方法重载的主要内容,如果未能解决你的问题,请参考以下文章