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中的稀疏数组与密集数组[译]
Sep 17 Javascript
jQuery遍历之next()、nextAll()方法使用实例
Nov 08 Javascript
深入浅析JavaScript中数据共享和数据传递
Apr 25 Javascript
JS基于面向对象实现的选项卡效果示例
Dec 20 Javascript
JavaScript中splice与slice的区别
May 09 Javascript
JavaScript文件的同步和异步加载的实现代码
Aug 19 Javascript
JavaScript中各数制转换全面总结
Aug 21 Javascript
vue-for循环嵌套操作示例
Jan 28 Javascript
详解react-refetch的使用小例子
Feb 15 Javascript
react-native滑动吸顶效果的实现过程
Jun 03 Javascript
vue随机验证码组件的封装实现
Feb 19 Javascript
详解Vue中$props、$attrs和$listeners的使用方法
Feb 18 Vue.js
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
thinkPHP框架实现图像裁剪、缩放、加水印的方法
2017/03/14 PHP
php 调用百度sms来发送短信的实现示例
2018/11/02 PHP
php生成HTML文件的类方法
2019/10/11 PHP
使用PHP+Redis实现延迟任务,实现自动取消订单功能
2019/11/21 PHP
JavaScript中使用构造器创建对象无需new的情况说明
2012/03/01 Javascript
Javascript中的delete介绍
2012/09/02 Javascript
jQuery Ajax异步处理Json数据详解
2013/11/05 Javascript
jquery操作下拉列表、文本框、复选框、单选框集合(收藏)
2014/01/08 Javascript
18个非常棒的jQuery代码片段
2015/11/02 Javascript
FullCalendar日历插件应用之数据展现(一)
2015/12/23 Javascript
简述Matlab中size()函数的用法
2016/03/20 Javascript
JavaScript入门教程之引用类型
2016/05/04 Javascript
解决bootstrap导航栏navbar在IE8上存在缺陷的方法
2016/07/01 Javascript
js替换字符串中所有指定的字符(实现代码)
2016/08/17 Javascript
在js代码拼接dom对象到页面上去的模板总结(必看)
2017/02/14 Javascript
老生常谈ES6中的类
2017/07/31 Javascript
vue滚动插件better-scroll使用详解
2019/10/18 Javascript
JavaScript实现PC端横向轮播图
2020/02/07 Javascript
mpvue 项目初始化及实现授权登录的实现方法
2020/07/20 Javascript
Python实现比较两个文件夹中代码变化的方法
2015/07/10 Python
python pandas实现excel转为html格式的方法
2018/10/23 Python
PyQt5实现从主窗口打开子窗口的方法
2019/06/19 Python
python可视化篇之流式数据监控的实现
2019/08/07 Python
Python openpyxl读取单元格字体颜色过程解析
2019/09/03 Python
python使用selenium爬虫知乎的方法示例
2020/10/28 Python
python 发送get请求接口详解
2020/11/17 Python
python模拟点击在ios中实现的实例讲解
2020/11/26 Python
新闻专业本科生的自我评价分享
2013/11/20 职场文书
节电标语大全
2014/06/23 职场文书
运动会广播稿150字(9篇)
2014/09/20 职场文书
校本培训个人总结
2015/02/28 职场文书
搞笑欢迎词大全
2015/09/30 职场文书
导游词之云南省玉龙雪山
2019/12/19 职场文书
mysql 数据插入优化方法之concurrent_insert
2021/07/01 MySQL
Spring Cloud 中@FeignClient注解中的contextId属性详解
2021/09/25 Java/Android
从结婚开始的恋爱故事。小说《我的美好婚事》TV动画化决定
2022/04/07 日漫