Javascript中无序的函数参数
Unordered function arguments in Javascript
下面是一个带有命名参数的正则函数:
function who(name, age, isMale, weight)
{
alert(name + ' (' + (isMale ? 'male' : 'female') + '), ' + age + ' years old, ' + weight + ' kg.');
}
who('Jack', 30, true, 90); //this is OK.
我想要实现的是;无论你是否按顺序传递论点;该函数应该产生类似的结果(如果不相同(:
who('Jack', 30, true, 90); //should produce the same result with the regular function
who(30, 90, true, 'Jack'); //should produce the same result
who(true, 30, 'Jack', 90); //should produce the same result
这使您能够以任何顺序传递参数列表,但仍将映射到逻辑顺序。到目前为止,我的方法是这样的:
function who()
{
var name = getStringInArgs(arguments, 0); //gets first string in arguments
var isMale = getBooleanInArgs(arguments, 0); //gets first boolean in arguments
var age = getNumberInArgs(arguments, 0); //gets first number in arguments
var weight = getNumberInArgs(arguments, 1); //gets second number in arguments
alert(name + ' (' + (isMale ? 'male' : 'female') + '), ' + age + ' years old, ' + weight + ' kg.');
}
这里有一个小问题;getStringInArgs()
和getNumberInArgs()
等函数每次都会遍历所有参数,以在指定位置按类型查找参数。我只能在args中迭代一次,并保留位置的标志,但之后我必须在who((函数中进行。
你认为这种方法是合乎逻辑的,也是唯一的方法吗?有更好的方法吗?
编辑1:上面的代码确实有效。我只是想知道是否有更好的方法。
编辑2:您可能想知道这是否有必要或是否有意义。主要原因是:我正在编写一个jQuery函数,它为DOM元素添加了一个特定的样式。我希望这个函数像对待简写的CSS值一样对待它的参数。
示例:
border: 1px solid red;
border: solid 1px red; /*will produce the same*/
所以;这是到目前为止真实的最终代码:
(function($){
function getArgument(args, type, occurrence, defaultValue)
{
if (args.length == 0) return defaultValue;
var count = 0;
for(var i = 0; i < args.length; i++)
{
if (typeof args[i] === type)
{
if (count == occurrence) { return args[i]; }
else { count++; }
}
}
return defaultValue;
}
$.fn.shadow = function()
{
var blur = getArgument(arguments, 'number', 0, 3);
var hLength = getArgument(arguments, 'number', 1, 0);
var vLength = getArgument(arguments, 'number', 2, 0);
var color = getArgument(arguments, 'string', 0, '#000');
var inset = getArgument(arguments, 'boolean', 0, false);
var strInset = inset ? 'inset ' : '';
var sValue = strInset + hLength + 'px ' + vLength + 'px ' + blur + 'px ' + color;
var style = {
'-moz-box-shadow': sValue,
'-webkit-box-shadow': sValue,
'box-shadow': sValue
};
return this.each(function()
{
$(this).css(style);
});
}
})(jQuery);
用法:
$('.dropShadow').shadow(true, 3, 3, 5, '#FF0000');
$('.dropShadow').shadow(3, 3, 5, '#FF0000', true);
$('.dropShadow').shadow();
我发现使用对象在未来更直接、更不容易出错:
var person = {
name: 'Jack',
age: 30,
isMale: true,
weight: 90
};
who(person);
function who(person){
alert(person.name +
' (' + (person.isMale ? 'male' : 'female') + '), ' +
person.age + ' years old, ' +
person.weight + ' kg.');
}
这样,当你几年后回来时,你就不必查看年龄是第一个、第二个还是第五个数字,也更能描述你想要实现的目标。
这似乎不必要地复杂,不仅从需要重新排列参数的函数的角度来看,而且从调用的人的角度来看。你说函数可以接受任何顺序的参数,但这并不完全正确。由于您确定哪个变量是基于类型的,因此它依赖于每个变量是不同的类型。名称和性别可以在任何地方,但数字参数必须按照特定的顺序。它还防止有人输入"30"或"90",这是数字,但会被视为字符串——将其与姓名混淆,无法找到年龄或体重。
您可以在参数数组中缓存特定类型的参数。这是一个大破解,您可以使用其他getTypeInArgs 遵循相同的模式
function getNumberInArgs(args, index) {
if (!args.numbers) {
args.numbers = [];
for (var i=0; i < args.length; i++) {
// You have to implement isNumber
if ( isNumber (args[i]) ) {
args.numbers.push(args[i];
}
}
}
return args.numbers[index];
}
我从来没有听说过以任何顺序接受参数,除了PHP中的内爆函数,由于历史原因,它在文档页面上被标记为一个大黑客。所以我不会这么做。如果顺序太混乱,我会使用WSkid所建议的获取文本对象的方法。
您可以尝试将参数数组复制到可以破坏性更新的东西中:
未经测试的代码:
编辑:我认为它现在可以工作了。
function args_getter(their_arguments){
//copy arguments object into an actual array
//so we can use array methods on it:
var arr = Array.prototype.slice.call(their_arguments);
return function(type){
var arg;
for(var i=0; i<arr.length; i++){
arg = arr[i];
if(type == typeof arg){
arr.slice(i, 1);
return arg;
}
}
return "do some error handling here"
}
}
function foo(){
var args = args_getter(arguments);
var b1 = args('boolean');
var b2 = args('boolean');
var n1 = args('number');
console.log(n1, b1, b2);
}
//all of
// foo(1, true, false),
// foo(true, 1, false), and
// foo(true, false, 1)
// should print (1, true, false)
这仍然是O(N^2(,因为你每次都要遍历数组。然而,除非函数可以接收数百个参数,否则这不应该是一个问题。
我同意格里芬的观点。这是不可能做到的,除非你限制了更多的选择。实际上,您有一个字符串、一个布尔值和两个数字。如果没有更多关于什么可以处于什么位置的规则,你就无法判断哪个数字是哪个。如果你愿意制定一些规则,关于哪个数字在前,或者哪个数字在其他争论之后,那么你可以把它整理出来。总的来说,我认为这是个坏主意。使用WSkid建议的对象要好得多(从良好编程的角度来看(。
无论如何,如果你想制定一个规则,比如体重必须在年龄之后,那么它可以这样做:
function findParm(args, type) {
for (var i = 0; i < args.length; i++) {
if (typeof args[i] == type) {
return(i);
}
}
return(-1);
}
function who(name, age, isMale, weight) {
// assumes all variables have been passed with the right type
// age is before weight, but others can be in any order
var _name, _age, _isMale, _weight, i;
var args = Array.prototype.slice.call(arguments);
_name = args[findParm(args, "string")]; // only string parameter
_isMale = args[findParm(args, "boolean")]; // only boolean parameter
i = findParm(args, "number"); // first number parameter
_age = args[i];
args.splice(i, 1); // get rid of first number
_weight = args[findParm(args, "number")]; // second number parameter
// you now have the properly ordered parameters in the four local variables
// _name, _age, _isMale, _weight
}
who("fred", 50, false, 100);
在这里工作:http://jsfiddle.net/jfriend00/GP9cW/.
我建议更好的编程是这样的:
function who(items) {
console.log(items.name);
console.log(items.age);
console.log(items.weight);
console.log(items.isMale);
}
who({name: "Ted", age: 52, weight: 100, isMale: true});
function who({name, age, isMale, weight})
{
alert(name + ' (' + (isMale ? 'male' : 'female') + '), ' + age + ' years old, ' + weight + ' kg.');
}
who({name:'Jack', age:30, isMale:true, weight90});
将参数作为对象,可以按任何顺序传递参数。
由于您有相同类型的参数,因此无法做到这一点。
除非年龄和体重有不重叠的范围,否则你不能这样做。根据体重或年龄,你应该如何区分30岁和60岁??
此代码:
function who(items) { console.log(items.name); console.log(items.age); console.log(items.weight); console.log(items.isMale);}who({name: "Ted", age: 52, weight: 100, isMale: true});
之前发的帖子似乎很明智。但为什么要让事情变得复杂呢。我的经验是,当人们把事情变得复杂时,事情就会出错。
BTW-上面的解决方案(正如前面发布的(类似于Perl解决方案。
- 函数参数中的数据与指定变量之间的任何性能差异
- AngularJS:我可以跳过函数参数回调吗
- 为什么不'我们在javascript中使用函数参数的数据类型
- 使用闭包共享构造函数参数
- 函数参数的值错误
- 当一个重要的构造函数参数丢失时应该发生什么
- 阻止ReSharper将JavaScript函数参数放到新行中
- 根据函数参数将CSS值存储在var中,然后对其进行操作
- 使构造函数参数具有ES6类方法的特权
- 当客户端将两个按钮的javascript函数参数修改为相同时,SQL/PHP会更新多行
- Windows.Networking.EndpointPair构造函数参数
- 是否可以使用Sinon.JS检查函数参数绑定是否正确
- 大括号中的Javascript函数参数
- jQuery 无法使用 AJAX 调用访问函数内部的函数参数
- 将JSON字符串转换为函数参数
- eval()读取函数参数有多糟糕
- Javascript不能在一个命令中使用函数参数
- 函数参数在内部不可见,返回新的Promise(函数(resolve,reject).传递给被promise化的函数的
- ES6类构造函数参数
- 是否可以在javascript函数参数列表中调用多个函数