淺談js中的引用和複製(傳值和傳址),淺談js

來源:互聯網
上載者:User

淺談js中的引用和複製(傳值和傳址),淺談js

好像一般很少人講到js中的引用和複製,不過弄清楚這個概念可以協助理解很多東西

先講一下很基礎的東西,看看js中幾種資料類型分別傳的什麼

引用:對象、數組、函數

複製:數字、布爾

字串單獨說明,因為它的特殊性,無法確定是傳遞引用還是複製數值(因為字串的值是沒法改變的,所以糾結這個問題也是沒意義的)但是用於比較的時候顯然是屬於傳值比較(稍後具體說比較的事)

下面講一下在使用中的具體體現

最普通的使用就是賦值了

var a = 1;var b = a;  //賦的是a的複製值b ++;alert(a);  //"1"  b的修改不影響a/****************************************/var a = [1];var b = a;   //賦的是a的引用 b[0] ++;alert(a); //"2"  b的修改對a也有效  不過當然b = [2];這種修改對a是沒用的。

函數的參數

傳值的傳遞:傳給函數的是數值的一個複製,函數中對其的修改外部不可見

var a = 1;var b = 2;function change(a,b) { var c = a; a = b;   //用新引用覆蓋 b = c; alert(a);  //"2"      alert(b);  //"1"}change(a,b);alert(a);  //"1"     alert(b);  //"2"

傳址的傳遞:傳給函數的是數值的一個引用,函數中對其屬性的修改外部可見,但用新引用覆蓋其則在外部不可見,比如

var a = [1, 2, 3];var b = [5, 6];function change(a,b) { a[0] = 4;  //對其屬性的修改外部可見  var c = a; a = b;   //用新引用覆蓋 b = c; alert(a);  //"5,6"      alert(b);  //"4,2,3"}change(a,b);alert(a);  //"4,2,3"alert(b);   //"5,6"

從結果可以看出a和b並沒有互換   因為用新引用覆蓋在外部不可見 這個很自然 因為函數只是拿到了引用 並沒有權力更改引用

下面這個就不同了

var a = [1, 2, 3];var b = [5, 6];function change() { var c = a; a[0] = 4; a = b; b = c;};change();alert(a);  //"5,6"alert(b);  //"4,2,3"

這裡成功實現互換 

又得提到js的塊級範圍了,這個放某些語言裡定然是要報未定義錯誤的,因為js沒有塊級範圍,所以它在change裡找不到變數a,b就會自覺的到上層去找,所以這裡的a,b是全域變數的引用

而上面的那個a,b則是change函數中的變數,在調用函數時傳遞了a,b的引用賦給了這兩個變數,但是並不能改變全域中的a,b,這裡換個名字大概就好理解多了

這個稍微提下    有些走題了。。。。

回到引用和複製 在比較運算中的注意事項

傳值的比較比較的是數值 而傳址的比較比較的是引用,引用不同即使數值相同也不等

1 == 1;  //true1 === 1;  //true[0] == [0]; //false[0][0] == [0][0];  //true[0][0] === [0][0];  //true[0].toString() == [0].toString();  //true 

閉包中。。。。

閉包大概是js中最糾結的東西 我們部門面試的經典試題,常考不衰啊。。。。

這裡我先不說閉包的東西,只說一下涉及傳值和引用的部分,等我哪天確定自己可以用清晰的條例、簡明的語言、生動的執行個體徹底的說清楚那個東西,再詳細介紹這個提js不能不提的傢伙。。。

閉包中,內建函式用外部函數的局部變數使用引用的方式而不是複製

其實這也是理解閉包的一個很重要的部分 可以用這個解釋一個很經典的閉包現象,很多地方在說明閉包的時候都會用到的一個例子

/*構造一個函數,給數組中的節點設定事件處理常式,當點擊一個節點時,alert出節點的序號*/var add_handlers = function (nodes) {  var i;  for (i = 0, l = nodes.length; i < l; i ++) {    nodes[i].onclick = function (e) {      alert(i);  // 當然這裡的結果必然是每次alert的都是節點總數。。。。    }  }};

為什麼每次alert的都是節點總數 而不是預期的序號呢,這個如果用複製和引用解釋就相當容易了

因為內建函式在使用外部變數時使用引用的方式而不是複製,就是說我給每個節點設定onclick事件的時候將i的引用傳遞給了alert,當我點擊節點觸發onclick事件的時候,i的值已經變成了節點總數。。。

var add_handlers = function (nodes) {  var i;  for (i = 0, l = nodes.length; i < l; i ++) {     nodes[i].onclick = function (i) {      return function(){      alert(i);        } }(i);  }};

這樣修改後之所以正確是因為此時傳進去的是i的值的複製,其實和普通函數是一樣的,不要因為加了閉包就迷糊了,迴歸本源去思考就明白了,本源就是上面講到的傳址的傳遞

順便提一句,不要被閉包這個古怪的名字唬住了,其實它和我們平時用的函數原理是一樣的,拋開那些“更長的生命週期”“保護私人變數”等閉包所謂的特性,把它當成一個普通的函數(也可以換個角度把全域函數看成一個特殊的閉包),很容易就可以理解了

關鍵是要放下所有的浮華,迴歸最本質。。。又跑題了。。。

以上這篇淺談js中的引用和複製(傳值和傳址)就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援幫客之家。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.