Js交換值的10種方法
在開發過程中又是我們需要對值進行交換。一般我們都在用一種簡單的解決方案:“臨時變數”。不過還有更好的辦法,而且不只有一個,有很多。有時我們在網上搜尋解決方案,找到後複製貼上,但是從沒想過這小段程式碼是怎樣工作的。現在我們該學習一下應該怎樣輕鬆高效地交換值了。
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,浮點數是一個問題。
廣州vi設計公司 http://www.maiqicn.com 我的007辦公資源網 https://www.wode007.com
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,僅僅返回第一個引數,不過這種交換方法效率不高。