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. <script type="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. <script type="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仍然改变的)。


  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值