JavaScript中交换值的10种方法总结


Posted in Javascript onAugust 18, 2020

前言

在开发过程中又是我们需要对值进行交换。一般我们都在用一种简单的解决方案:“临时变量”。不过还有更好的办法,而且不只有一个,有很多。有时我们在网上搜寻解决方案,找到后复制粘贴,但是从没想过这小段代码是怎样工作的。现在我们该学习一下应该怎样轻松高效地交换值了。

1 使用临时变量

先是最简单的一种。

function swapWithTemp(num1,num2){
 console.log(num1,num2)

 var temp = num1;
 num1 = num2;
 num2 = temp;

 console.log(num1,num2)
}

swapWithTemp(2.34,3.45)

2 使用算术运算符 + 和 -

还可以用一些数学魔术来交换值。

function swapWithPlusMinus(num1,num2){
 console.log(num1,num2)

 num1 = num1+num2;
 num2 = num1-num2;
 num1 = num1-num2;

 console.log(num1,num2)
}

swapWithPlusMinus(2.34,3.45)

让我们来看看它是如何工作的。我们在第 4 行获得两个数字的总和。现在,如果从和中减去一个数字,那么另一个数字就正确了。这就是第 5 行所做的工作。从存储在 num1 变量中的总和中减去 num2 会得到存储在 num2 中的原始 num1 值。同样,在第 6 行的 num1 中得到 num2 的值。

小心:还有一个与 + 和 - 互换的单行代码方案,不过。。。

它是这样的:

function swapWithPlusMinusShort(num1,num2){
 console.log(num1,num2)

 num2 = num1+(num1=num2)-num2;

 console.log(num1,num2)
}

swapWithPlusMinusShort(2,3)

上面的代码给出了预期的结果。 () 中的表达式将 num2 存储在 num1 中,然后减去 num1 - num2,除了减去 num2 - num2 = 0 之外什么也没有做,因此得到了结果。但是当使用浮点数时,会看到一些意外的结果。

试着执行下面的代码并查看结果:

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)
}

//Try with - operator
swapWithPlus(2.3,3.4)

上面的代码是有效的,但牺牲了可读性。在第 4 行的 () 中,我们将 num1 赋值给 num2,而旁边的 0 是返回值。简而言之,第 4 行的运算逻辑如下所示:

num2 = num1 + 0 
=> num2 = num1.

所以得到了正确结果。

注意:一些 JavaScript 引擎可能会对上面的代码进行优化,从而忽略 + 0。

4 使用算术运算符 * 和 /

让我们用 * 和/ 运算符玩更多的花样。

其原理与先前的方法相同,但是有一些小问题。

function swapWithMulDiv(num1,num2){
 console.log(num1,num2)

 num1 = num1*num2;
 num2 = num1/num2;
 num1 = num1/num2;

 console.log(num1,num2)
}

swapWithMulDiv(2.34,3.45)

与上一个方法相同。首先得到两个数字的乘积,并将它们存储在 num1 中。然后在第 5 行,把 num2 与这个结果相除,得到第一个数字,然后重复此过程以获得第二个数字。

现在你成“数学家” 了。

不过那小问题在哪儿呢?

让我们来尝试一下:

function swapWithMulDiv(num1,num2){
 console.log(num1,num2)

 num1 = num1*num2;
 num2 = num1/num2;
 num1 = num1/num2;

 console.log(num1,num2)
}

//试着改变数字的值,看看会发生什么
swapWithMulDiv(2.34,0)

我们的值没有交换,而是得到了一个奇怪的 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)

没错,又是 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)

 num2 = num1*(num1=num2)/num2;

 console.log(num1,num2)
}

swapWithMulDivShort(2.3,3.4)

上面的代码类似于用 + 和 - 进行交换时的较短的代码。把 num2 赋值给 num1,然后第 4 行的演算逻辑是这样:

num2 = num1 * num2 / num2
 => num2 = num1

这样两个值就互换了。

5)仅使用 * 或 / 运算符

function swapWithMul(num1,num2){
 console.log(num1,num2)

 num2 = num1 * (num1=num2, 1)

 console.log(num1,num2)
}

//Try with / and ** operator
swapWithMul(2.3,3.4)

上面的程序是有效的,但牺牲了可读性。在第 4 行的  () 中,我们将 num1 赋值给 num2,旁边的 1 是返回值。简而言之,第 4 行的逻辑如下所示:

num2 = num1 * 1 
 => num2 = num1

这样就得到了结果。

6 使用按位异或(XOR)。

XOR 用来进行二进制位运算。当有两个不同的输入时,它的结果为 1,否则为 0。

X Y X^Y
1 1 0
1 0 1
0 1 1
0 0 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)

10 的4 位二进制数 -> 1010

1 的 4 位二进制数 -> 0001

现在:

第四行: 
num1 = num1 ^ num2 
 => 1010 ^ 0001 
 => 1011 
 => 7 
第五行: 
num2 = num1 ^ num2 
 => 1011 ^ 0001 
 => 1010 
 => 10
第六行: 
num1 = num1 ^ num2 
 => 1011 ^ 1010 
 => 0001 
 => 1

两个值交换了。

再来看另一个例子:

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)

嗯??交换的值在哪儿?我们只是得到了数字的整数部分,这就是问题所在。 XOR 假定输入是整数,所以···相应地执行计算。但是浮点数不是整数,而是由 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)
}
// 试试 infinities 和整数值.
swapWithXOR(-Infinity,Infinity)

毫无意外,我们没有得到预期的结果。这是因为 Infinity 和 ? Infinity 都是浮点数。正如我们在前面所讨论的,对于 XOR,浮点数是一个问题。

7 使用按位同或 (XNOR)

它用来进行二进制位运算,但是与 XOR 正好相反。当有两个不同的输入时,XNOR 的结果是 0,否则结果为 1。 JavaScript 没有执行 XNOR 的运算符,所以要用 NOT 运算符对 XOR 的结果求反。

X Y XNOR
1 1 1
1 0 0
0 1 0
0 0 1

先了解其工作原理:

function swapWithXNOR(num1,num2){
 console.log(num1,num2)

 num1 = ~(num1^num2);
 num2 = ~(num1^num2);
 num1 = ~(num1^num2);

 console.log(num1,num2)
}

//可以试试负值
swapWithXNOR(10,1)

10 的 4 位二进制数 -> 1010

1 的 4 位二进制数 -> 0001

第 4 行:

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

由于这是一个负数,所以需要将其转换回二进制并计算 2 的补码来获取十进制值,例如:

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

第 5 行:

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

第 6 行:

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)

8 在数组中进行赋值

这是一线技巧。只需要一行代码就可以进行交换,更重要的是,无需数学运算,只需要数组的基本知识。不过它看上去可能很奇怪。

先让看看它的实际效果:

function swapWithArray(num1,num2){
 console.log(num1,num2)

 num2 = [num1, num1 = num2][0];

 console.log(num1,num2)
}

swapWithArray(2.3,Infinity)

在数组的下标 0 位置中存储 num1,在下标 1 中,既将 num2 分配给 num1,又存储了 num2。另外,我们只是访问 [0],将数组中的 num1 值存储在 num2 中。而且可以在这里交换我们想要的任何东西,比如:整数、浮点数(包括无穷数)以及字符串。看上去很整洁,但是在这里失去了代码的清晰度。

9 使用解构表达式

这是 ES6 的功能。这是所有方法中最简单的。只需要一行代码就可以完成交换:

let num1 = 23.45;
let num2 = 45.67;

console.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,仅仅返回第一个参数,不过这种交换方法效率不高。

总结

本文探讨了用于在 JavaScript 中对值进行交换的众多方法。希望对你有所帮助!

到此这篇关于JavaScript中交换值的10种方法就介绍到这了,更多相关JavaScript交换值方法内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
javascript 获取网页参数系统
Jul 19 Javascript
JavaScript对象和字串之间的转换实例探讨
Apr 21 Javascript
js怎么终止程序return不行换jfslk
May 30 Javascript
Jquery显示、隐藏元素以及添加删除样式
Aug 09 Javascript
jQuery获取Radio,CheckBox选择的Value值(示例代码)
Dec 12 Javascript
实例讲解使用原生JavaScript处理AJAX请求的方法
May 10 Javascript
将json转换成struts参数的方法
Nov 08 Javascript
jQuery UI仿淘宝搜索下拉列表功能
Jan 10 Javascript
AngularJS表格添加序号的方法
Mar 03 Javascript
jQuery表单验证之密码确认
May 22 jQuery
详解如何使用Node.js编写命令工具——以vue-cli为例
Jun 29 Javascript
js中getBoundingClientRect的作用及兼容方案详解
Feb 01 Javascript
js+css3实现炫酷时钟
Aug 18 #Javascript
纯js+css实现在线时钟
Aug 18 #Javascript
three.js 利用uv和ThreeBSP制作一个快递柜功能
Aug 18 #Javascript
js+css实现扇形导航效果
Aug 18 #Javascript
js实现3D旋转效果
Aug 18 #Javascript
Vue elementui字体图标显示问题解决方案
Aug 18 #Javascript
详解三种方式在React中解决绑定this的作用域问题并传参
Aug 18 #Javascript
You might like
Phpbean路由转发的php代码
2008/01/10 PHP
PHP 数据库树的遍历方法
2009/02/06 PHP
Yii2使用小技巧之通过 Composer 添加 FontAwesome 字体资源
2014/06/22 PHP
适用于初学者的简易PHP文件上传类
2015/10/29 PHP
php简单统计在线人数的方法
2016/05/10 PHP
CakePHP框架Model关联对象用法分析
2017/08/04 PHP
解决PHPstudy Apache无法启动的问题【亲测有效】
2020/10/30 PHP
一个JS小玩意 几个属性相加不能超过一个特定值.
2009/09/29 Javascript
js禁止小键盘输入数字功能代码
2011/08/01 Javascript
js在数组中删除重复的元素自保留一个(两种实现思路)
2014/08/22 Javascript
深入理解JavaScript系列(44):设计模式之桥接模式详解
2015/03/04 Javascript
浅谈JS中逗号运算符的用法
2016/06/12 Javascript
js 奇葩技巧之隐藏代码
2017/08/11 Javascript
ionic2懒加载配置详解
2017/09/01 Javascript
详解微信小程序开发聊天室—实时聊天,支持图片预览
2019/05/20 Javascript
[00:12]2018DOTA2亚洲邀请赛 Sccc亮相SOLO赛,今年他又会有什么样的战绩?
2018/04/06 DOTA
[03:12]完美世界DOTA2联赛PWL DAY6集锦
2020/11/05 DOTA
python操作MongoDB基础知识
2013/11/01 Python
Python使用MYSQLDB实现从数据库中导出XML文件的方法
2015/05/11 Python
Python实现基于多线程、多用户的FTP服务器与客户端功能完整实例
2017/08/18 Python
python 字典 setdefault()和get()方法比较详解
2019/08/07 Python
Python3使用腾讯云文字识别(腾讯OCR)提取图片中的文字内容实例详解
2020/02/18 Python
Pytho爬虫中Requests设置请求头Headers的方法
2020/09/22 Python
css3 按钮样式简单可扩展创建
2013/03/18 HTML / CSS
css3新单位vw、vh的使用教程
2018/03/23 HTML / CSS
Nili Lotan官网:Nili Lotan同名品牌
2018/01/07 全球购物
YII2 全局异常处理深入讲解
2021/03/24 PHP
文明学生标兵事迹
2014/01/21 职场文书
室内设计专业自荐信
2014/05/31 职场文书
敬老院标语
2014/06/27 职场文书
政治学专业毕业生求职信
2014/08/11 职场文书
党的群众路线教育实践活动个人对照检查材料(校长)
2014/11/05 职场文书
2014年物业公司工作总结
2014/11/22 职场文书
蓬莱阁导游词
2015/02/04 职场文书
诗词赏析-(浣溪沙)
2019/08/13 职场文书
62句有关感恩节文案(推荐收藏)
2019/11/28 职场文书