交换两个参数值的更好方法是什么?

时间:2011-12-12 23:26:36

标签: javascript

所以给定一个函数

function foo( a, b ) {

}

现在,如果我想交换参数ab的值,我可以这样写:

var t = a;
a = b;
b = t;

然而,这是一个丑陋的模式 - 它需要三个语句(三行代码),加上一个局部变量。现在,我可以承担三个声明,但必须声明那个烦人的辅助变量?我想避免这种情况。

那么,有什么更好的方法呢? (更好的代码行(可能是单行代码),或者不声明局部变量。)

我想出了这个:

(function ( t ) { a = b; b = t; })( a ); // swap a and b

现场演示: http://jsfiddle.net/J9T22/

那么,你能想出什么?

10 个答案:

答案 0 :(得分:14)

使用它的功能?的严重吗

最简单的往往是最好的:

var t = a;
a = b;
b = t;

如果您使用它,例如对于服务器端JS(即您只需要支持一个 JavaScript引擎),您也可以使用解构赋值语法:

[a, b] = [b, a]

答案 1 :(得分:8)

这是一个有趣的小练习。

你可以这样做:a=[b][b=a,0]

var a='a';
var b='b';
a=[b][b=a,0];
alert(a + ', ' + b); // "b, a"

同样来自我的+1,无视仇敌;)

......哦等等!这个不是是一个有趣的小练习,但实际上是用于现实世界吗?那么你最好不要这样做,因为它的可读性低于var t = a; a = b; b = t!

a=[b][b=a,0];      // wth?
var t=a; a=b; b=t; // ahhh so readable!

但是,不,严肃地说,这样做实际上给你带来了比必须创建另一个变量更好的好处,因为你可以做到这一点。 Var声明通常不能成为普通语句的一部分,因此尝试执行(var t=a; a=b; b=t)之类的操作只会抛出一个SyntaxError,但(a=[b][b=a,0])计算结果为a,这可能很有用。

讨论这样的事情很有意思,因为在我们的生产代码中,以非常规的方式做事可能不受欢迎,这是学习语言的好方法。那(我认为)就是SO的全部意义所在。我休息一下。

答案 2 :(得分:5)

在Mozilla的Javascript 1.7中,您可以[a, b] = [b, a]

答案 3 :(得分:3)

我读过你不应该这样做但是......

a=5;
b = 7
//add parenthesis to make this do what it should in one line
a ^= b;
b ^= a;
a ^= b; 

他们现在应该拥有彼此的价值观。 [编辑]根据pointedears的描述,这不符合规定,但这里描述了它是如何工作的...但是,正如已经陈述的(由其他人)坚持最简单的。没有理由这样做,你不会注意到任何性能提升,你的代码将变得不那么可读。

http://en.wikipedia.org/wiki/XOR_swap_algorithm

在这里它正在行动...... http://jsfiddle.net/nHdwH/

答案 4 :(得分:3)

如果您仅允许Mozillafuture ES6 stuff,则可以使用解构分配:

[a,b] = [b,a]

如果最大的担忧是环境污染可变,你可以借用arguments对象。

arguments[arguments.length] = a;
a = b;
b = arguments[arguments.length];

但这有点长。


或者您可以将对象分配给现有参数:

a = {a:a,b:b};
b = a.a;
a = a.b;

function foo( a, b ) {
    a = {a:a,b:b};
    b = a.a;
    a = a.b;
    console.log(a,b);  'baz' 'bar'
}

foo('bar','baz');

或者删除像这样的东西:

a = {b:b,a:(b=a)};
a = a.b;

或者直到一行:

a = {b:b,a:(b=a)}.b;

目前在“严格模式”支持的实现中,您可以执行此操作(如果您实际上是以“严格模式”运行)

a = b; b = arguments[0];

这是因为对形式参数的更改对arguments对象没有影响,反之亦然。

答案 5 :(得分:1)

  

交换两个参数值的更好方法是什么?

没有“更好”的方式,只有一些渐渐变得模糊不清的方式。

有些人可能认为其他方法“聪明”,我想其中有些方法是,但我不想与任何认为他们实际上“更好”的人合作,因为我不希望看到这样的方法在实际项目代码中出现。

“聪明”数学方法只有在你假设整数值时才有效,所以在我看来,由于你没有指定类型,所以它们是错误的。

如果您发现丑陋的三个陈述,您可以这样做:

var t;
t = a, a = b, b = t;

是的,它实际上是一样的,但至少它将交换代码全部放在同一行。

(尽管如此,我认为如果没有浏览器支持,[a, b] = [b, a];会“更好”。)

答案 6 :(得分:0)

如果值是整数,那么您可以使用算术来完成工作:

function foo( a, b ) {
    a = -(b = (a += b) - b) + a;
    console.log(a);
    console.log(b);
}

foo(1,2);

请参阅http://www.greywyvern.com/?post=265

答案 7 :(得分:0)

a=[a,b];
b=a[0];
a=a[1];

这只使用变量a和b,但它会创建一个数组, 这比临时变量更重要。

使用临时变量。

var t = a; A = B; B =吨;

另一个理智的支持。

答案 8 :(得分:0)

我略微不同意其他人,这可能很有用。但是,将其内联定义为坏,坏,坏,坏,坏。如果你打算这样做,它应该是一个更高阶的函数:

function flip(fn) {
  return function(a, b) {
     return fn.call(null, b, a);
  };
}

例如:

function log() {
   console.log.apply(console, arguments);
}

flip(log)(1, 2); // 2 1

现在这看起来很愚蠢,但是当你进行映射/缩减/迭代等时,这种事情经常发生。说你有一些功能:

function doSomeStuff(index, value) {
  // complex stuff happening here
}

一个数组:

var arr = ["foo", "bar", "etc"];

如果您要使用,例如,在此数组上映射并需要调用doSomeStuff,您必须手动滚动此功能:

arr.map(function(value, index) {
  return doSomeStuff(index, value);
});

虽然你可以说这并不坏,但它会分散你想要做的事情(只是称之为该死的功能!)。有了这个更高阶的函数,它可以简化为:

arr.map(flip(doSomeStuff));

如果您想要更完整的翻转功能,您可以:

function flip(fn) {
  return function() {
     var args = Array.prototype.slice.call(arguments);
     return fn.apply(null, args.reverse());
  };
}

现在:

flip(log)(1,2,3,4,5); // 5 4 3 2 1

答案 9 :(得分:0)

我认为在现实世界中,人们会希望这种交换是有条件的。

[a,b] = c? [a,b] : [b,a]

你也可以用[a,b] [+ c]替换a的所有实例,用[b,a] [+ c]替换所有b的实例,如:

arr.sort( (a,b) => [a,b][+c] - [b,a][+c] )

或只是有一个函数来调用函数:

swapMyFunction = (a,b) => myFunction(b,a)