javascript學習之swap函數


  最近想自學javascript,今天一邊查書一邊學着寫一些簡單的函數之類的東西,由於之前學過C語言,自然而然的想着js中是否也有像C里面的指針,引用形參之類的東西,於是想寫個交換兩個變量的值的函數(swap),然而似乎不太簡單。

  我在網上找到了一段如下的代碼,

View Code
1 function swap(a,b)
2 // This function is come from internet.
3 // URL@ http://bbs.51js.com/thread-65058-1-1.html
4 {
5 var temp=a;
6 this.a=b;
7 this.b=temp;
8 };

發現運行結果似乎是正常的,當我給a,b賦值后調用這個函數,輸出的確是把a,b的值交換了。然而這段代碼是錯誤的,個人覺得這個錯誤很有意思,就mark一下。O(∩_∩)O~

至於為什么是錯誤的,帖子中名為“井底之蛙”的朋友解釋了(當然我是初學,也不知道這個解釋對不對,完不完整),但覺得挺有道理,姑且貼過來吧:

“不要混淆了自己,也誤導了別人。
樓主不清楚javascript的function參數的值傳遞特點以及指針、引用的概念。所以才會問出這樣的問題,答案很明確,swap是不能實現的。當然,你可以通過js語言動態特征,如:反射來變相地實現,比如海浪的提供的例子。
而樓上Rimifon的代碼的思路不清晰:
function 不通過 new 的方式調用,其內部上下文中的this其實是指向 window 對象。所以上面例子場景中的function swap相當於:
function swap(a,b)
{
var temp=a;
window.a=b;
window.b=temp;
}
很明顯,實際上你在function中寫死了“全局”變量a,b的名稱。swap 不能起到swap 參數a,b 的作用。”

我自己試了一下,再定義變量c,d,調用swap(c,d),發現調用的結果並不是交換c,d的值,而是把c,d的值賦給了a,b,並交換a,b的值,從這一點來看,a,b的確是全局變量,這樣的函數是不能夠達到我想要交換變量的作用的。

在帖子中,一位叫“海浪”的朋友給出了這樣的方法:

View Code
 1  <script>
 2 function swap($a,$b)
 3 {
 4 var temp=eval($a);
 5 eval($a+"="+$b);
 6 eval($b+"=temp");
 7 }
 8 var a=3,b=4;
 9 swap("a","b");
10 document.write(a+" "+b);
11 </script>

 這段代碼讓我感興趣的地方有三個,一個是美元符號$,一個是eval()方法,還有就是調用的方式(在調用時變量a要寫出'a')。

  關於美元符號$,網上的說法有的說是prototype.js中的,有的說是jQuery中的,這個我暫時搞不清楚(初學者嘛,先不要在一個點糾結太久,不然就卡死了),不過大部分的說法是:

“$() 方法是在DOM中使用過於頻繁的 document.getElementById() 方法的一個便利的簡寫,就像這個DOM方法一樣,這個方法返回參數傳入的id的那個元素。

比起DOM中的方法,這個更勝一籌。你可以傳入多個id作為參數然后 $() 返回一個帶有所有要求的元素的一個 Array 對象。”

也就是說,美元符號$是函數 document.getElementById()的簡寫(個人也覺得寫這個名字好長,好麻煩,哈哈)。下面是幾個關於prototype.js的網址,內容還不錯 one, two, three,mark一下,以后再詳細去了解。有點跑題了,這里的美元符號$只是一個變量名字的定義,跟那個函數方法沒有啥關系,目的是為了盡量避免重名,因為重名的話就無法達到交換變量的目的了。

  關於eval(),先看看w3c中的解釋“eval() 函數可計算某個字符串,並執行其中的的 JavaScript 代碼”,我的理解,eval()是執行其參數(字符串)中的命令的意思,所以上述函數大概是這樣子的,當調用swap('a','b')時,在swap函數內部,首先是變量$a的值為‘a',變量$b的值為'b',然后執行var temp=eval($a)時,也就是執行eval('a'),即temp=a;(其實函數swap內找不到a,b,我想它可能是在找不到變量時就去this中找吧,當然這個我不確定),后面的代碼也是如此,所以當輸入參數為'a','b'時,實際執行的應該是

View Code
1 var temp=a;
2 a=b;
3 b=temp;

當參數為'c','d'時,實際執行的應該是

View Code
1 var temp=c;
2 c=d;
3 d=temp;

這樣就達到了交換變量的作用了,但是,當輸入的字符串恰好等於形參名時,情況就會出錯,例如輸入為'$a'和'$b'時,其代碼的實際執行情況應該是這樣的

View Code
1 var temp='$a';
2 $a=$b;
3 $b=temp;

函數執行的結果是把$a='$b',$b='$a',並沒有實現交換變量的值的功能。而且如果在另一個函數中定義了新的a,b,並調用這個swap,它並不會改變這個函數中的a和b的值,而是改變了最外層的a和b的值。

  這樣一來,調用的方式為什么不是a,而是'a'也就很清楚了,因為要調用eval的緣故,里面的參數要是string。

綜上所述,這兩種方法都不能夠真正合理的實現swap的方法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM