题
什么是最好的方式(s)伪造的功能重载在Javascript?
我知道这是不可能超载功能在Javascript作为在其他语言。如果我需要一个功能有两个用途的 foo(x)
和 foo(x,y,z)
这是最好的/首选方式:
- 使用不同的名字在第一位
- 使用可选择的论点像
y = y || 'default'
- 使用参数的数量
- 检查类型的参数
- 或者怎么样?
解决方案
这样做的最佳方法的功能重载有参数并不是要检查参数长度或类型;检查的类型将只是让你的代码慢,你们的乐趣阵列,空值,对象,等等。
什么大多数开发做的就是粘在一个对象为最后的参数,以他们的方法。这个目的可以举行任何东西。
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"});
然后你能处理它无论如何你想在你的的方法。[关,如果-别,等等。]
其他提示
我经常这样做:
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
这个特别的例子是,实际上更加优雅javascript比。参数,这是不指定的'不确定的'javascript中,它评估为false if发言。然而,该功能的定义并没有传达的信息,p2和p3是可选择的。如果你需要很多的负载过重。已经决定使用对象为参数,例如,习阿贾克斯(选择)。我同意他们,这是最强大和最明确有稽可查的方法重载,但是我很少需要多一个或两个快速可选择的参数。
编辑:如果改变测试每伊恩*的建议
有没有真正的功能重载在JavaScript因为它允许通过任何数量的参数的任何类型。你检查里面的职能多少 参数 已经过去了,什么类型。
正确的答案是没有过载在JAVASCRIPT。
检查/开关内部的功能不重载。
该概念载:在一些编程语言功能超载或方法的过载是能够创建多种方式相同的名称用不同的方式实现的。呼叫要过多功能运行的一个具体执行这一功能适宜的上下文中的呼吁,允许一个功能,呼吁进行不同的任务,根据上下文。
例如,doTask()和doTask(对象O)超载方法。叫后者,一个目的必须传递作为一个参数,而前者不需要参数,并被称为具有空参数的领域。一个共同错误就是分配一个默认值中的对象的第二种方法,这将导致在一个模糊的叫错误,作为编译器不会知道这两种方法的使用。
https://en.wikipedia.org/wiki/Function_overloading
所有建议的实现是巨大的,但真理被告知,没有本地实现JavaScript。
有两种方法,你可能方法本更好:
通过一词典(associative array)如果你想留下一个很大的灵活性
采取的一个目作为参数和使用原型的基于继承,以增加灵活性。
这是一种方法,允许真正的方法超载使用的参数类型,如下所示:
Func(new Point());
Func(new Dimension());
Func(new Dimension(), new Point());
Func(0, 0, 0, 0);
编辑(2018年):由于这是写在2011年,直接方法调用已经大大增加,同时速超载方法都没有。
它不是一个办法,我会推荐,但它是一个有价值的思想运动要想想如何可以解决这些类型的问题。
这是一个基准不同的方法- https://jsperf.com/function-overloading.它显示了这一职能载(把类型虑)可以围绕 13倍慢 在谷歌 铬是V8 作为的 16.0(测试).
以及传递对象(即 {x: 0, y: 0}
),也可以采取的C种方法在适当的时候,命名方法的相应。例如,矢量。AddVector(矢量),矢量。AddIntegers(x、y、z,...)和矢量。AddArray(integerArray).你可以看看C库,例如照片名灵感。
编辑:我已经增加了一个基准,用于传递对象和测试对象的使用 'param' in arg
和 arg.hasOwnProperty('param')
, 和功能的过载是多快于传递一个目和检查的性质(在这一基准至少).
从设计的角度看,功能重载是唯一有效的或合乎逻辑的,如果超载参数对应于同样的行动。所以按理说应该有一个基本方法,是只关注具体的详细信息,否则,可指示不适当的设计选择。因此,一个也能够解决使用的功能重载的数据转换到相应的对象。当然,必须考虑的范围的问题,因为没有需要作出精心的设计如果你的目的只是打印一个名字,但对所设计的框架和库这样的想法是有道理的。
我来自一个执行矩形,因此所提到的维和点。也许可以添加一个矩形 GetRectangle()
法 Dimension
和 Point
原型,然后将该功能超载问题的排序。和什么有关原语?好了,我们已经争论的长度,现在是一个有效的测试对象,因为有一个 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);
最好的方法实际上取决于功能和参数。你的每一个选项是一个很好的想法在不同的情况。我通常这些尝试按下列顺序,直到他们中的一个工作:
使用可选择的论点像y=y||"默认"。 这是便利的如果你可以做到这一点,但它可能并不总是实际的,例如当0/null/未定义将是一个有效的参数。
使用的参数数目。 类似于最后的选择,但可能工作的时候#1不起作用。
检查类型的论点。 这可能在某些情况下工作的数量参数是相同的。如果你不能可靠地确定的类型,可能需要用不同的名称。
使用不同的名字在第一位。 你可能需要这样做,如果其他的选择不工作、不实际,或对一致性的其它相关功能。
如果我需要一个功能有两个采用foo(x)和foo(x、y、z)这是最好的/佳方式?
问题是,JavaScript本身不支持的方法超载。所以,如果它认为/分析两个或更多的功能与一个名称相同,这只会考虑的最后一个定义的功能和复盖以前的。
一的方式我认为是适合于大多数情况下-
可以说,你有方法
function foo(x)
{
}
而不是超载方法 这是不可能的。 你可以定义新的方法
fooNew(x,y,z)
{
}
然后修改第1功能如下:
function foo(arguments)
{
if(arguments.length==2)
{
return fooNew(arguments[0], arguments[1]);
}
}
如果你有很多这样的超载方法考虑使用 switch
不仅仅是 if-else
发言。
(更多细节)
PS:上面的链接进入我的个人的博客,有其他详细信息。
我不确定关于最佳做法,但这里是我如何做到这一点:
/*
* Object Constructor
*/
var foo = function(x) {
this.x = x;
};
/*
* Object Protoype
*/
foo.prototype = {
/*
* f is the name that is going to be used to call the various overloaded versions
*/
f: function() {
/*
* Save 'this' in order to use it inside the overloaded functions
* because there 'this' has a different meaning.
*/
var that = this;
/*
* Define three overloaded functions
*/
var f1 = function(arg1) {
console.log("f1 called with " + arg1);
return arg1 + that.x;
}
var f2 = function(arg1, arg2) {
console.log("f2 called with " + arg1 + " and " + arg2);
return arg1 + arg2 + that.x;
}
var f3 = function(arg1) {
console.log("f3 called with [" + arg1[0] + ", " + arg1[1] + "]");
return arg1[0] + arg1[1];
}
/*
* Use the arguments array-like object to decide which function to execute when calling f(...)
*/
if (arguments.length === 1 && !Array.isArray(arguments[0])) {
return f1(arguments[0]);
} else if (arguments.length === 2) {
return f2(arguments[0], arguments[1]);
} else if (arguments.length === 1 && Array.isArray(arguments[0])) {
return f3(arguments[0]);
}
}
}
/*
* Instantiate an object
*/
var obj = new foo("z");
/*
* Call the overloaded functions using f(...)
*/
console.log(obj.f("x")); // executes f1, returns "xz"
console.log(obj.f("x", "y")); // executes f2, returns "xyz"
console.log(obj.f(["x", "y"])); // executes f3, returns "xy"
我只是尝试这样做,也许适合你的需要。根据这些论点,可以访问不同的功能。你初始化第一次称呼它。和功能地图隐藏在封闭。
TEST = {};
TEST.multiFn = function(){
// function map for our overloads
var fnMap = {};
fnMap[0] = function(){
console.log("nothing here");
return this; // support chaining
}
fnMap[1] = function(arg1){
// CODE here...
console.log("1 arg: "+arg1);
return this;
};
fnMap[2] = function(arg1, arg2){
// CODE here...
console.log("2 args: "+arg1+", "+arg2);
return this;
};
fnMap[3] = function(arg1,arg2,arg3){
// CODE here...
console.log("3 args: "+arg1+", "+arg2+", "+arg3);
return this;
};
console.log("multiFn is now initialized");
// redefine the function using the fnMap in the closure
this.multiFn = function(){
fnMap[arguments.length].apply(this, arguments);
return this;
};
// call the function since this code will only run once
this.multiFn.apply(this, arguments);
return this;
};
测试它。
TEST.multiFn("0")
.multiFn()
.multiFn("0","1","2");
由于JavaScript没有载功能的选择对象可用来代替。如果有一个或两个必要的参数,这是更好地保持他们的独立选择对象。这里的一个例子是关于如何使用的选择对象和人口稠密的价值为默认值的情况下,如果价值是不是通过了在选择对象。
function optionsObjectTest(x, y, opts) {
opts = opts || {}; // default to an empty options object
var stringValue = opts.stringValue || "string default value";
var boolValue = !!opts.boolValue; // coerces value to boolean with a double negation pattern
var numericValue = opts.numericValue === undefined ? 123 : opts.numericValue;
return "{x:" + x + ", y:" + y + ", stringValue:'" + stringValue + "', boolValue:" + boolValue + ", numericValue:" + numericValue + "}";
}
在这里, 是一个例子如何使用的选择对象
有没有办法能重载在javascript。因此,我建议如下通过 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!!");
}
}
祝你好运!
介绍
迄今为止通过阅读这么多的答案会给人一个头痛的问题。任何人都想知道的概念将需要知道的 以下先决条件s.
Function overloading Definition
, Function Length property
, Function argument property
Function overloading
在最简单的形式意味着一个功能执行不同任务的基础上的参数数目,正在通过它。值得注意的是该任务1,TASK2和TASK3是强调下,正在执行的基础上的数目 arguments
正在通过同样的功能 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不提供的内置能力的功能重载。
替代
约翰E Resig(创造者JS)指出可替代其采用上述先决条件实现能力要实现的功能重载。
下面的代码使用一个简单而幼稚的方法通过使用 if-else
或 switch
发言。
- 评估
argument-length
财产。 - 不同的数值结果在援引不同的功能。
var ninja = {
whatever: function() {
switch (arguments.length) {
case 0:
/* do something */
break;
case 1:
/* do something else */
break;
case 2:
/* do yet something else */
break;
//and so on ...
}
}
}
另一种技术是更清洁和活力。这突出显示的这种技术是的 addMethod
一般功能。
我们定义的一个函数
addMethod
这是用来增加不同功能的一个目的 相同的名称 但 不同的功能.下面的
addMethod
功能接受的三个参数对象的名字object
, 、功能的名字name
与功能,我们想要调用fn
.- 内部
addMethod
定义var old
存储所参考的以前的function
被保存的帮助下关闭了保护泡沫。
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
增加三个职能时援引使用ninja.whatever(x)
与数量的参数x
这可以是任何东西,即无论是空白或者一个或多个调用不同的功能定义,同时利用addMethod
功能。
var ninja = {};
debugger;
addMethod(ninja,'whatever',function(){ console.log("I am the one with ZERO arguments supplied") });
addMethod(ninja,'whatever',function(a){ console.log("I am the one with ONE arguments supplied") });
addMethod(ninja,'whatever',function(a,b){ console.log("I am the one with TWO arguments supplied") });
ninja.whatever();
ninja.whatever(1,2);
ninja.whatever(3);
另一种方式方法,这是通过使用特别的变量: 参数, 这是一个执行情况:
function sum() {
var x = 0;
for (var i = 0; i < arguments.length; ++i) {
x += arguments[i];
}
return x;
}
所以你可以修改这些代码为:
function sum(){
var s = 0;
if (typeof arguments[0] !== "undefined") s += arguments[0];
.
.
.
return s;
}
看看这个。这是非常凉爽。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
作为这一员额已经包含很多不同的解决方案,我认为我后的另外一个。
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
function overload() {
var functions = arguments;
var nroffunctionsarguments = [arguments.length];
for (var i = 0; i < arguments.length; i++) {
nroffunctionsarguments[i] = arguments[i].length;
}
var unique = nroffunctionsarguments.filter(onlyUnique);
if (unique.length === arguments.length) {
return function () {
var indexoffunction = nroffunctionsarguments.indexOf(arguments.length);
return functions[indexoffunction].apply(this, arguments);
}
}
else throw new TypeError("There are multiple functions with the same number of parameters");
}
这可以使用如下所示:
var createVector = overload(
function (length) {
return { x: length / 1.414, y: length / 1.414 };
},
function (a, b) {
return { x: a, y: b };
},
function (a, b,c) {
return { x: a, y: b, z:c};
}
);
console.log(createVector(3, 4));
console.log(createVector(3, 4,5));
console.log(createVector(7.07));
这个方案是不完美的,但我仅要表明它如何可以做到的。
你可以用户的'就从约翰Resig.用这种方法可以"超负荷"方法的基础上参数。
// addMethod - By John Resig (MIT Licensed)
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 - By Stavros Ioannidis
function addMethod(obj, name, fn) {
obj[name] = obj[name] || function() {
// get the cached method with arguments.length arguments
var method = obj[name].cache[arguments.length];
// if method exists call it
if ( !! method)
return method.apply(this, arguments);
else throw new Error("Wrong number of arguments");
};
// initialize obj[name].cache
obj[name].cache = obj[name].cache || {};
// Check if a method with the same number of arguments exists
if ( !! obj[name].cache[fn.length])
throw new Error("Cannot define multiple '" + name +
"' methods with the same number of arguments!");
// cache the method with fn.length arguments
obj[name].cache[fn.length] = function() {
return fn.apply(this, arguments);
};
}
转接模式=>的最佳做法JS超载
前进到另一个功能,其名称是建立从第3和4点:
- 使用参数的数量
- 检查类型的参数
window['foo_'+arguments.length+'_'+Array.from(arguments).map((arg)=>typeof arg).join('_')](...arguments)
应用程序在的情况:
function foo(){
return window['foo_'+arguments.length+Array.from(arguments).map((arg)=>typeof arg).join('_')](...arguments);
}
//------Assuming that `x` , `y` and `z` are String when calling `foo` .
/**-- for : foo(x)*/
function foo_1_string(){
}
/**-- for : foo(x,y,z) ---*/
function foo_3_string_string_string(){
}
其他复杂的样品:
function foo(){
return window['foo_'+arguments.length+Array.from(arguments).map((arg)=>typeof arg).join('_')](...arguments);
}
/** one argument & this argument is string */
function foo_1_string(){
}
//------------
/** one argument & this argument is object */
function foo_1_object(){
}
//----------
/** two arguments & those arguments are both string */
function foo_2_string_string(){
}
//--------
/** Three arguments & those arguments are : id(number),name(string), callback(function) */
function foo_3_number_string_function(){
let args=arguments;
new Person(args[0],args[1]).onReady(args[3]);
}
//--- And so on ....
功能重载,通过动态性在100行JS
- VanillaJS,没有外部的依赖
- 全浏览器支持- 阵列。原型。切片, 对象。原型。toString
- 1114字节uglify会/744字节g-拉链
这是从一个大体的代码,其中包括 isFn
, isArr
, 等等。类型的检查功能。该VanillaJS版下面,已经修改,以删除所有外部的依赖,但是你将要限定你自己类型的检查功能的使用在 .add()
呼叫。
注: 这是一个自我执行功能(那我们可以有一个封闭范围内),因此分配 window.overload
而不是 function overload() {...}
.
window.overload = function () {
"use strict"
var a_fnOverloads = [],
_Object_prototype_toString = Object.prototype.toString
;
function isFn(f) {
return (_Object_prototype_toString.call(f) === '[object Function]');
} //# isFn
function isObj(o) {
return !!(o && o === Object(o));
} //# isObj
function isArr(a) {
return (_Object_prototype_toString.call(a) === '[object Array]');
} //# isArr
function mkArr(a) {
return Array.prototype.slice.call(a);
} //# mkArr
function fnCall(fn, vContext, vArguments) {
//# <ES5 Support for array-like objects
//# See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply#Browser_compatibility
vArguments = (isArr(vArguments) ? vArguments : mkArr(vArguments));
if (isFn(fn)) {
return fn.apply(vContext || this, vArguments);
}
} //# fnCall
//#
function registerAlias(fnOverload, fn, sAlias) {
//#
if (sAlias && !fnOverload[sAlias]) {
fnOverload[sAlias] = fn;
}
} //# registerAlias
//#
function overload(vOptions) {
var oData = (isFn(vOptions) ?
{ default: vOptions } :
(isObj(vOptions) ?
vOptions :
{
default: function (/*arguments*/) {
throw "Overload not found for arguments: [" + mkArr(arguments) + "]";
}
}
)
),
fnOverload = function (/*arguments*/) {
var oEntry, i, j,
a = arguments,
oArgumentTests = oData[a.length] || []
;
//# Traverse the oArgumentTests for the number of passed a(rguments), defaulting the oEntry at the beginning of each loop
for (i = 0; i < oArgumentTests.length; i++) {
oEntry = oArgumentTests[i];
//# Traverse the passed a(rguments), if a .test for the current oArgumentTests fails, reset oEntry and fall from the a(rgument)s loop
for (j = 0; j < a.length; j++) {
if (!oArgumentTests[i].tests[j](a[j])) {
oEntry = undefined;
break;
}
}
//# If all of the a(rgument)s passed the .tests we found our oEntry, so break from the oArgumentTests loop
if (oEntry) {
break;
}
}
//# If we found our oEntry above, .fn.call its .fn
if (oEntry) {
oEntry.calls++;
return fnCall(oEntry.fn, this, a);
}
//# Else we were unable to find a matching oArgumentTests oEntry, so .fn.call our .default
else {
return fnCall(oData.default, this, a);
}
} //# fnOverload
;
//#
fnOverload.add = function (fn, a_vArgumentTests, sAlias) {
var i,
bValid = isFn(fn),
iLen = (isArr(a_vArgumentTests) ? a_vArgumentTests.length : 0)
;
//#
if (bValid) {
//# Traverse the a_vArgumentTests, processinge each to ensure they are functions (or references to )
for (i = 0; i < iLen; i++) {
if (!isFn(a_vArgumentTests[i])) {
bValid = _false;
}
}
}
//# If the a_vArgumentTests are bValid, set the info into oData under the a_vArgumentTests's iLen
if (bValid) {
oData[iLen] = oData[iLen] || [];
oData[iLen].push({
fn: fn,
tests: a_vArgumentTests,
calls: 0
});
//#
registerAlias(fnOverload, fn, sAlias);
return fnOverload;
}
//# Else one of the passed arguments was not bValid, so throw the error
else {
throw "poly.overload: All tests must be functions or strings referencing `is.*`.";
}
}; //# overload*.add
//#
fnOverload.list = function (iArgumentCount) {
return (arguments.length > 0 ? oData[iArgumentCount] || [] : oData);
}; //# overload*.list
//#
a_fnOverloads.push(fnOverload);
registerAlias(fnOverload, oData.default, "default");
return fnOverload;
} //# overload
//#
overload.is = function (fnTarget) {
return (a_fnOverloads.indexOf(fnTarget) > -1);
} //# overload.is
return overload;
}();
使用:
呼叫者限定其载的职能的分配变量的回归 overload()
.感谢链接,其他重载可能被定义系列:
var myOverloadedFn = overload(function(){ console.log("default", arguments) })
.add(function(){ console.log("noArgs", arguments) }, [], "noArgs")
.add(function(){ console.log("str", arguments) }, [function(s){ return typeof s === 'string' }], "str")
;
这个可选择的参数 overload()
定义"默认"功能的电话,如果该签署不能确定。的参数 .add()
有:
fn
:function
定义过载;a_vArgumentTests
:Array
的function
s确定的试验运行的arguments
.每function
接受一个参数和返回true
你的基础上,如果争论是否有效;sAlias
(Optional):string
定义的别名以直接访问过载功能(fn
),例如myOverloadedFn.noArgs()
将呼吁这一职能直接,避免了动态性测试的参数。
这个执行实际上允许不仅仅是传统的功能重载,作为第二 a_vArgumentTests
参数 .add()
在实践中的定义定义的类型。所以,你可以栅论点不仅基于类型,但是在范围、价值或收藏品的价值。
如果你看看过145行代码 overload()
你会看到的,每个签名是分类的数量 arguments
通过它。这样做的目的是,我们的人数有限的试验,我们正在运行。我还跟踪一个叫计数。一些额外的代码,列载的职能可以重新排序,使得更多的通常所称的功能进行测试第一,再次加入一些衡量业绩的增强。
现在,有一些警告...作为Javascript是松散的类型,你必须要小心你的 vArgumentTests
作为一个 integer
可以验证一个 float
, 等等。
JSCompress.com 版本(1114字节,744个字节g-拉链):
window.overload=function(){'use strict';function b(n){return'[object Function]'===m.call(n)}function c(n){return!!(n&&n===Object(n))}function d(n){return'[object Array]'===m.call(n)}function e(n){return Array.prototype.slice.call(n)}function g(n,p,q){if(q=d(q)?q:e(q),b(n))return n.apply(p||this,q)}function h(n,p,q){q&&!n[q]&&(n[q]=p)}function k(n){var p=b(n)?{default:n}:c(n)?n:{default:function(){throw'Overload not found for arguments: ['+e(arguments)+']'}},q=function(){var r,s,t,u=arguments,v=p[u.length]||[];for(s=0;s<v.length;s++){for(r=v[s],t=0;t<u.length;t++)if(!v[s].tests[t](u[t])){r=void 0;break}if(r)break}return r?(r.calls++,g(r.fn,this,u)):g(p.default,this,u)};return q.add=function(r,s,t){var u,v=b(r),w=d(s)?s.length:0;if(v)for(u=0;u<w;u++)b(s[u])||(v=_false);if(v)return p[w]=p[w]||[],p[w].push({fn:r,tests:s,calls:0}),h(q,r,t),q;throw'poly.overload: All tests must be functions or strings referencing `is.*`.'},q.list=function(r){return 0<arguments.length?p[r]||[]:p},l.push(q),h(q,p.default,'default'),q}var l=[],m=Object.prototype.toString;return k.is=function(n){return-1<l.indexOf(n)},k}();
你现在可以实现的功能重载在写2018年没有polyfills,检查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"
什么是传播法?
其余/性传播对于写的建议(第4阶段)增加了传播性为目的文本。它将复制自己的可枚举的性质从一个提供对象到一个新的对象。 更多关于mdn
注:传播法在目文本不工作中的边缘,即它是一个实验性的特征。 见浏览器的兼容性
第一种选择真正值得关注,因为这是我已经在相当复杂码的安装。因此,我的答案是
- 使用不同的名字在第一位
有一个小小的但却是必要的提示、名称看起来应该不同于计算机的,但不适用于你。姓名载的职能,如:func,func1,func2.
这是一个古老的问题而是一个我认为需要另一个项目(虽然我怀疑有人会读)。使用的立即援引的功能表现形式(生活)可以结合使用封锁和内联的功能允许用于功能超载。请考虑以下(预谋)的例子:
var foo;
// original 'foo' definition
foo = function(a) {
console.log("a: " + a);
}
// define 'foo' to accept two arguments
foo = (function() {
// store a reference to the previous definition of 'foo'
var old = foo;
// use inline function so that you can refer to it internally
return function newFoo(a,b) {
// check that the arguments.length == the number of arguments
// defined for 'newFoo'
if (arguments.length == newFoo.length) {
console.log("a: " + a);
console.log("b: " + b);
// else if 'old' is a function, apply it to the arguments
} else if (({}).toString.call(old) === '[object Function]') {
old.apply(null, arguments);
}
}
})();
foo(1);
> a: 1
foo(1,2);
> a: 1
> b: 2
foo(1,2,3)
> a: 1
总之,采用的生活创建了一个地方范围,使我们能够界定的私人变 old
储存引用的初始定义功能 foo
.这个函数,然后返回一个内联的功能 newFoo
记录内容的两个论点如果是通过了两个参数 a
和 b
或者电话的 old
如果功能 arguments.length !== 2
.这种模式可以是任何重复的次数,以赋予一个变量与几个不同的功能defitions.
JavaScript类型的语言,我只是觉得有意义要超载方法/多功能方面的数量参数。因此,我建议,以检查是否的参数,已经被定义的:
myFunction = function(a, b, c) {
if (b === undefined && c === undefined ){
// do x...
}
else {
// do y...
}
};
为2017年,以下已被共同的技术。注意,我们还可以执行的类型检查,内的功能。
function f(...rest){ // rest is an array
console.log(rest.length);
for (v of rest) if (typeof(v)=="number")console.log(v);
}
f(1,2,3); // 3 1 2 3
你使用的情况下,这是怎么我会解决它与 ES6
(由于它已经结束2017年):
const foo = (x, y, z) => {
if (y && z) {
// Do your foo(x, y, z); functionality
return output;
}
// Do your foo(x); functionality
return output;
}
你可以明显地适应这项工作与任何数量的参数,只是更改有条件的声明。
这样的事情可以做了功能超载。
function addCSS(el, prop, val) {
return {
2: function() {
// when two arguments are set
// now prop is an oject
for (var i in prop) {
el.style[i] = prop[i];
}
},
3: function() {
// when three arguments are set
el.style[prop] = val;
}
}[arguments.length]();
}
// usage
var el = document.getElementById("demo");
addCSS(el, "color", "blue");
addCSS(el, {
"backgroundColor": "black",
"padding": "10px"
});
我们做了 over.js 为了解决这个问题是一个非常优雅的方式。你可以这样做:
var obj = {
/**
* Says something in the console.
*
* say(msg) - Says something once.
* say(msg, times) - Says something many times.
*/
say: Over(
function(msg$string){
console.info(msg$string);
},
function(msg$string, times$number){
for (var i = 0; i < times$number; i++) this.say(msg$string);
}
)
};
所以我真的很喜欢这种方式做事,我发现在秘密的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);
}
}
}
你再使用就要加重载的职能的任何对象。主要混淆这个代码对我来说是使用fn。长==的论点。长--这是因为,fn。长度是的数量预计参数,同时参数。长度数量的参数,实际上是所谓的功能。原因的匿名的功能,无论是因为你可以通过在任何数量的参数在javascript和语言是宽容。
我喜欢这个因为你可以用它无处不在-只是创建这个功能,只需使用的方法在什么代码基你想要的。
它还避免具有一个可笑的大如果/交换机的声明,其中变得很难阅读,如果你开始写作的复杂代码(接受的答案会导致在此)。
在缺点,我想代码最初是一点点模糊的...但是我不确定的其他人呢?
我想分享的一个有用的例子超载样的方法。
function Clear(control)
{
var o = typeof control !== "undefined" ? control : document.body;
var children = o.childNodes;
while (o.childNodes.length > 0)
o.removeChild(o.firstChild);
}
使用:明();//清除所有的文档
明(myDiv);//清理小组引用的myDiv
我喜欢@AntouanK的做法。我经常发现自己提供的功能,与不同的数字o参数和不同的类型。有时他们不要遵循的顺序。我用图寻找的类型参数:
findUDPServers: function(socketProperties, success, error) {
var fqnMap = [];
fqnMap['undefined'] = fqnMap['function'] = function(success, error) {
var socketProperties = {name:'HELLO_SERVER'};
this.searchServers(socketProperties, success, error);
};
fqnMap['object'] = function(socketProperties, success, error) {
var _socketProperties = _.merge({name:'HELLO_SERVER'}, socketProperties || {});
this.searchServers(_socketProperties, success, error);
};
fqnMap[typeof arguments[0]].apply(this, arguments);
}