14

JavaScript 交换值的方法,你能想到几种?

 3 years ago
source link: http://developer.51cto.com/art/202009/626485.htm
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

早期之前,在 JS 中交换值,我们主要还是使用临时变量。ES6 之后,我们可以使用展开运算符号来交换变量,除了这两种方式,你还能想到哪些呢?

本文主要介绍 交换变量的 10 种方法,请过目

1. 使用临时变量

function swapWithTemp(num1, num2) { console.log(num1, num2) let temp = num1 num1 = num2 num2 = temp console.log(num1, num2)}swapWithTemp(66.66, 8.88)

2. 使用算术运算符+和-

function swapWithPlusMinus(num1, num2){ console.log(num1, num2) num1 = num1 + num2 num2 = num1 - num2 num1 = num1 - num2 console.log(num1, num2)}swapWithPlusMinus(66, 8)

主要的过程是这样的,先求出两个数的和,那么第二个数要换友第一个数的的值就是总的和减去第二个,也就是代码中的 num2 = num1-num2,同理,第一个数要换成第二个数的值,就是总的和减去第一个数的值,现在第一个数已经是赋值给第二个数,所以直接减去第二数的值即可,也就是 num1 = num1-num2

但我试了一下小数,好像有点问题,有点尴尬 ,但这种思想我们还是要掌握的

上面还可以这样来简写 :

function swapWithPlusMinusShort(num1, num2){ console.log(num1, num2) num2 = num1 + (num1 = num2) - num2 console.log(num1, num2)}

这里的技巧在于 (num1 = num2) ,这步,我们让 num1 等于 num2了,并且返回是num2 的值,此时 num1 值已交换。接着就用 num1 加上 (num1 = num2) 返回的值,也就是 num1 + num2 求和,然后思路就和上面分析的一样了 。

但是,使用浮点数时,也会得到一些意外的结果

你可以在控制台跑跑下面这段代码:

function swapWithPlusMinusShort(num1, num2){ console.log(num1, num2) num2 = num1 + (num1 = num2) - num2 console.log(num1, num2)}swapWithPlusMinusShort(2,3.1)

3.仅使用+或-运算符

只要使用+运算符,就可以得到与同时使用+和-一样的结果 。

function swapWithPlus(num1, num2){ console.log(num1, num2) num2 = num1 + (num1=num2, 0) console.log(num1, num2)}swapWithPlus(2.3,3.4)

上面的程序可以工作,但牺牲了可读性。在()中,我们将num1分配给num2,旁边的0是返回值。简而言之,第4行看起来是这样的 ✍:

num2 = num1 + 0 => num2 = num1

4. 使用算术运算符*和/

*和/的原理与先前的方法相同,只是有一些微小的区别 。

function swapWithMulDiv(num1, num2){ console.log(num1, num2) num1 = num1*num2 num2 = num1/num2 num1 = num1/num2 console.log(num1, num2)}swapWithMulDiv(2.3,3.4)

与上一个相同。我们得到两个数字的乘积并将它们存储在其中一个变量中,对应就是num1 = num1*num2。然后,用总数除了对应的变量,得到交换后变量的值 。

但这个有些问题是什么呢?就是,如果有交换值有 0 就会得到意想不到的问题 :

swapWithMulDiv(2.34,0)// 2.34 0// NaN NaN

我们的值没有交换,而是得到一个奇怪的NaN。那是怎么回事?如果你还记得你的数学课,我们总是被告知不要除以0因为它是未定义。原因在于极限是如何起作用的,还有一些其他的原因,我们不会涉及。现在,让我们看看这个方法的其他问题:

function swapWithMulDiv(num1, num2){ console.log(num1, num2) num1 = num1*num2 num2 = num1/num2 num1 = num1/num2 console.log(num1, num2)}swapWithMulDiv(2.34,Infinity)// 2.34 Infinity// NaN NaN

又是NaN,因为我们不能用Infinity除以任务内容,因此未定义 ⚡。

如果是负无穷大呢,结果又会是怎么样 :

function swapWithMulDiv(num1, num2){ console.log(num1, num2) num1 = num1*num2 num2 = num1/num2 num1 = num1/num2 console.log(num1, num2)}swapWithMulDiv(2.34,-Infinity)

-Infinity的结果与前面的示例相同,原因也是一样的。

下面是上面的一个简写方式,当然存在问题也是一样的:

function swapWithMulDivShort(num1, num2){ console.log(num1, num2) num1 = num1*num2 num2 = num1*(num1=num2)/num2 num1 = num1/num2 console.log(num1, num2)}swapWithMulDivShort(2.3,3.4)

5. 仅使用*或/运算符

上面的程序可以工作,但牺牲了可读性。在()中,我们将num1分配给num2,旁边的1``是返回值。num2 = num1 * (num1=num2, 1)看起来是这样的:

num2 = num1 * 1 => num2 = num1

6. 使用按位异或

异或是按二进制位来工作,当我们有两个值不一样时,它的结果为1,否则为0:

function swapWithXOR(num1, num2){ console.log(num1, num2) num1 = num1^num2; num2 = num1^num2; num1 = num1^num2; console.log(num1, num2)}swapWithXOR(10,1)

4位二进制数10-> 1010

4位二进制数1-> 0001

上面的分解过程 :

num1 = num1 ^ num2 = 1010 ^ 0001 = 1011num2 = num1 ^ num2 = 1011 ^ 0001 => 1010 => 10num1 = num1 ^ num2 = 1011 ^ 1010 => 0001 => 1

JavaScript语言精髓与编程实践(第3版)

作者:周爱民

当当

我们来看另一个例子。

function swapWithXOR(num1, num2){ console.log(num1, num2) num1 = num1^num2; num2 = num1^num2; num1 = num1^num2; console.log(num1, num2)}swapWithXOR(2.34,3.45)// 2.34 3.45// 3 2

嗯?交换的值在哪里?我们只得到这个数的整数部分。这就是问题所在。异或假设输入是整数,因此执行相应的计算。但是浮点数不是整数,并且由IEEE 754标准来表示,该标准将数字分为三部分:一个符号位、一组表示指数的位以及另一组表示1(包括)到2(不包括)之间的数字尾数,因此我们得到了不正确的值。

另一个例子:

function swapWithXOR(num1, num2){ console.log(num1, num2) num1 = num1^num2; num2 = num1^num2; num1 = num1^num2; console.log(num1, num2)}swapWithXOR(-Infinity,Infinity)// -Infinity Infinity// 0 0

再一次,我们没有看到预期的结果 。这是因为Infinity和–Infinity都是浮点数。正如我们上面讨论的,对于XOR,浮点数是一个问题。

使用同或门 XNOR。

同或门也称为异或非门,它也可以操作二进制位,与XOR相反。当我们有两个值不一样时,XNOR 结果是0,否则为1。JavaScript 没有一个操作符来执行XNOR,所以我们使用非与XOR操作符来达到类似的效果。

function swapWithXNOR(num1, num2){ console.log(num1, num2) num1 = ~(num1^num2) num2 = ~(num1^num2) num1 = ~(num1^num2) console.log(num1, num2)}swapWithXNOR(10,1)

4位二进制数10-> 1010

4位二进制数1-> 0001

上面的分解过程 :

num1 = ~(num1 ^ num2) => ~(1010 ^ 1011)=> ~(1011) => ~11 => -12

由于我们有一个负数,我们需要将其转换回二进制并执行2的补码以获取十进制值,例如:

-12 => 1100 => 0011 + 1 => 0100

num2 = ~(num1 ^ num2) => ~(0100 ^ 0001) => ~(0101) => ~5 => -6-6 => 0110 => 1001 + 1 => 1010 => 10

num1 = ~(num1 ^ num2) => ~(0100^ 1010) => ~(1110) => ~14 => -15-15 => 1111 => 0000 + 1 => 0001 => 1

花费了一些时间,但我们交换了价值。但不幸的是,它遇到了与XOR相同的问题,它不能处理浮点数和无穷大 。

function swapWithXNOR(num1, num2){ console.log(num1, num2) num1 = ~(num1^num2) num2 = ~(num1^num2) num1 = ~(num1^num2) console.log(num1, num2)}swapWithXNOR(2.3,4.5)// 2.3 4.5// 4 2

8. 在数组中赋值

这是一个简单的技巧,只需要一行来执行交换,更重要的是不需要数学知识,只需要一个基本的数组知识即可。

function swapWithArray(num1, num2){ console.log(num1, num2) num2 = [num1, num1 = num2][0] console.log(num1, num2)}swapWithArray(2.3,Infinity)// 2.3 Infinity// Infinity 2.3

在数组的索引0中,我们存储num1,在索引1中,我们既将num2分配给num1,又存储了num2。 另外,访问[0],将数组中的num1值存储在num2中。

这种方式可以交换我们想要的任何东西,包括整数,浮点数(包括无穷大)以及字符串,它很整洁,但清晰度不够。

9. 使用解构表达式

这是ES6的一个特性,也是最简单的,我们可以像这样交换值 :

let num1 = 23.45let num2 = 45.67console.log(num1,num2)[num1,num2] = [num2,num1]console.log(num1,num2)

10. 使用立即调用的函数表达式(IIFE)

IIFE指的是在定义后立即执行的函数。

function swapWithIIFE(num1,num2){ console.log(num1,num2) num1 = (function (num2){ return num2; })(num2, num2=num1) console.log(num1,num2)}swapWithIIFE(2.3,3.4)

在上面的示例中,我们立即调用第4行上的一个函数。最后的括号是函数的参数。第二个参数将num1分配给num2,第一个参数num1被返回。因此,交换了这些值,请记住,这种交换方法效率不高。

【责任编辑:赵宁宁 TEL:(010)68476606】


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK