1. 程式人生 > >js陣列及物件的賦值和引用

js陣列及物件的賦值和引用

   簡要歸納:

   1、普通的賦值是複製棧區內容。

   2、基本型別的資料在棧區存放資料自身,var a=b; //a與b無關。

        引用型別資料在棧區存放資料地址。  var a=b; //a,b聯動

   3、基本資料型別包括:undefined,boolean,number,string,null

         引用型別:物件、陣列、函式。

舉例說明:

引數傳遞:

js的函式引數傳遞為值傳遞,個人理解傳參是複製了份棧區內容給函式。只不過基本型別棧區存放資料,所以傳入值與原值等值但不相關;引用型別棧區存放資料地址,傳入值為一個地址,所以傳入值和原值都可以通過地址訪問或修改堆區資料。

1、當傳入的是 基本型別的引數時:就是複製了份內容給i而已,i與age之間沒有關係。

function setAge(i)

{     alert(i);  //24     i = 18;     alert(i);  //18,i的改變不會影響外面的age }; var age = 24; setAge(age); alert(age);//24

2、當傳入的引數為引用型別時:複製了地址給函式,函式可通過地址修改堆區資料。

function setName(obj)

{     obj.name = 'haha'; }; var obj2 = new Object(); setName(obj2);
alert(obj2.name);    //  haha 這看起來很像是傳遞的是引用,因為obj.name受到改變了,但其實不是,其實還是值,因為obj2本身的值就是新物件的地址,所以傳進去的就是這個地址。 例子:
  1. var a = [1, 2, 3];  
  2. var b = [5, 6];  
  3. var c=100;
  4. function change(a,b,c) {  
  5.   c=99;
  6.   a[0] = 4;     
  7.   var c = a;  
  8.   a = b;       
  9.   b = c;  
  10. }  
  11. change(a,b,c);  
  12. alert(c);    //"100";
  13. alert(a);    //"4,2,3"  
  14. alert(b);     //"5,6"  
這道題也有些迷惑性。呼叫了交換函式,但a與b的實際值並不交換。因為函式中只是新建立了一個與a,b棧區所存地址相同的引數。也就是說函式中的a,b,c都不是函式外的a,b,c .不會修改其棧區內容。

另一個例子:

var [1,2,3];

var a;

[4,5,6];

alert(b);  //[1,2,3]

 看了前面的內容,此處很容易認為第三步時修改了地址指向的資料,從1,2,3修改為4,5,6, 所以alert(b);  //[4,5,6]

但要搞清建立物件和其他的區別。第三步意味建立了一個[4,5,6]的物件,並將其地址賦給a. 所以a不再指向[1,2,3].

同理,若想要b有a的值,但不想聯動。可以有以下方法:

方法一:用jq的$.extend方法

[html] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. <scripttype="text/javascript">
  2. var a=[1];  
  3. var b;  
  4. b= $.extend(true,{},a)  
  5. b[0]++;  
  6. alert(b[0]);   
  7.     </script>

方法二:用陣列的concat方法 [html] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. <scripttype="text/javascript">
  2. var a=[1];  
  3. var b=a.concat();  
  4. b[0]++;  
  5. alert(a[0]);   
  6.     </script>

方法三:for迴圈陣列,挨個賦值。

var a=[1,2,3];

var b=[];

for(var i=0; i<a.length; i++){

  b[i]=a[i];

}

方法四:陣列的slice()方法。

arrayObject.slice(start,end)
返回一個新陣列,包含從start到end(不包含此元素)的arrayObject中元素。該方法不修改原陣列,而是返回一個新陣列。
var arr =["a","b","c","d","e"];
var arr1=arr.slice(2,4);
console.log(arr1);            //"c,d"
var arr2=arr.slice(0);
console.log(arr2);            //"a,b,c,d,e"
arr2[2]="wang"
console.log(arr);            //"a,b,c,d,e" 與原陣列不聯動
console.log(arr2);           //"a,b,wang,d,e"

阿里2014年的筆試題:

var a = 1;

var obj = {     b: 2 }; var fn = function () {}; fn.c = 3; function test(x, y, z) {     x = 4;     y.b = 5;     z.c = 6;     return z; } test(a, obj, fn); alert(a + obj.b + fn.c);

答案:12

 首先test傳遞進去的實參中,a是基本型別(,複製了一份值),obj是object(指向地址,你動我也動),fn也當然不是基本型別啦。在執行test的時候,x被賦值為4(跟a沒關係,各玩各的,a仍然為1),y的b被賦值為5,那obj的b也變為5,z的c變為6,那fn的c當然也會是6. 所以alert的結果應該是1+5+6 =12. (其實test不返回z也一樣,z仍然改變的)。