下面是一个带有命名参数的常规函数:
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()
等函数每次都会遍历所有参数,以便在指定位置找到类型的arg。我可以只遍历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();
答案 0 :(得分:5)
我发现将来使用对象更直接,更不容易出错:
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.');
}
这样,当你多年后回来时,你不必查找年龄是第一个,第二个还是第五个数字,并且更能描述你想要实现的目标。
答案 1 :(得分:2)
这似乎不必要地复杂,不仅仅是从函数的角度来看,它需要重新排序其参数,而且还要从调用者的角度来看。你说该函数可以接受任何顺序的参数,但这并不完全正确。由于您确定哪个变量基于类型,因此它依赖于每个变量是不同的类型。名称和性别可以是任何位置,但数字参数必须按特定顺序排列。它还可以阻止某人传入“30”或“90”,这些数字是数字但会被视为字符串 - 将其与名称混淆并且没有找到年龄或体重。
答案 2 :(得分:1)
您可以在arguments数组中缓存特定类型的参数。这是大黑客,您可以使用与其他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中的implode函数,并且由于历史原因,它在documentation页面上被标记为大黑客。所以我不会这样做。如果订单太混乱,我会按照WSkid的建议使用获取文字对象的方法。
答案 3 :(得分:1)
您可以尝试将arguments数组复制到可以破坏性更新的内容中:
未经测试的代码: 编辑:我认为它现在有效。
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),因为每次都要经过数组。但是,除非您的函数可以接收数百个参数,否则这不应成为问题。
答案 4 :(得分:0)
由于你有相同类型的参数,所以你无法做到这一点。
除非年龄和体重不重叠范围,否则您无法执行此操作。你如何区分体重或年龄30到60岁?
答案 5 :(得分:0)
我同意格里芬的观点。除非您限制的选择多于您的选择,否则无法完成此操作。实际上,你有一个字符串,一个布尔值和两个数字。如果没有更多关于什么位置的规则,你就不知道哪个数字是哪个。如果你愿意做一些关于哪个数字首先出现的规则,或者哪个数字出现在其他参数之后,那么你可以对其进行排序。总的来说,我认为这是一个坏主意。使用像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});
答案 6 :(得分:0)
此代码:
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解决方案类似。
答案 7 :(得分:0)
function who({name, age, isMale, weight})
{
alert(name + ' (' + (isMale ? 'male' : 'female') + '), ' + age + ' years old, ' + weight + ' kg.');
}
who({name:'Jack', age:30, isMale:true, weight90});
将参数作为对象,允许您以任何顺序传递参数。