zoukankan      html  css  js  c++  java
  • JS 的引用赋值与传值赋值

    这个问题说大不大说小不小,如果你有幸踩了这个坑,一定会找这篇文章,哈哈~

    现说一下JS数字的类型:基本类型引用类型

    先看下下面两个栗子:

    var a = 30;
    var b = a;
    a = 20;
    console.log( b )   // 30
    
    var a = [1,2];
    var b = a;
    a[0] = 5;
    console.log( b )  // [5,2]
    

    简单的说:

    number,string类型都是基本类型,而基本类型存放在栈区,访问时按值访问,赋值是按照普通方式赋值;

    对象和数组是通过引用来赋值的,所以改变a的同时b也会跟着改变。

    解决办法:

    1. var a = [1,2];
    var b = a.slice(0);
    b[0] = 3;
    alert(a) //1,2
     
    2. var a = [1,2];
    var b = a.concat(0);
     
    concat会直接返回新的数组对象

    好了下面详细的说,看了上面秒懂的直接忽略(直接看下面阿里的面试题);

    1、基本类型

    基本的数据类型有:undefined,boolean,number,string,null。 基本类型存放在栈区,访问是按值访问的,就是说你可以操作保存在变量中的实际的值。

    当基本类型的数据赋值时,赋得是实际的值,a和b是没有关联关系的,b由a复制得到,相互独立。(字面量的才是基本类型)

    var a=10;

    var b=a;

    console.log(a+','+b);    // 10,10
    a++;
    console.log(a+','+b)  // 11,10
     

    2、引用类型

    引用类型指的是对象。可以拥有属性和方法,并且我们可以修改其属性和方法。引用对象存放的方式是:在栈中存放对象变量标示名称和该对象在堆中的存放地址,在堆中存放数据。

    对象使用的是引用赋值。当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在堆中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。

     

     3、数组是引用类型

    我们先来看一个例子:

    var [1,2,3];

    var a;

    [4,5,6];

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

     好像数组是基本类型一样。。,但是:

    var [1,2,3];

    var a;

    a.pop();

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

    这是怎么回事?因为:(知乎解释)

    a = [4,5,6];//改变的是a引用本身,没有改变数组对象,a和b没有了关系。
    a.pop();//改变的是数组对象,a引用没有改变。
    b = a;//该操作后,b直接指向数组对象,不是b指向a,a再指向数组。
    //所以改变a引用并不会对b引用造成影响,改变数组对象可以。

    作者:Intopass
    链接:https://www.zhihu.com/question/26042362/answer/31903017
    来源:知乎

    这个问题就跟我之前在React todo-list 一篇中提到的问题一样:

    var tasks=this.state.data;
      tasks=tasks.filter(function(i){
         return i.index!=taskId;  
     });

    由于filter函数是返回一个新的数组,虽然仍然用tasks去接收,但这时候tasks的指向已经是新数组啦,所以tasks和data已经不在有关系。(concat也是返回新数组)

     而push和splice函数是在原数组上操作,所谓在原数组操作,指的是指向不变,所以tasks和data是相关联的。

     

    4、参数传递

    js的函数参数传递为值传递。

    当传入的是 基本类型的参数时:就是复制了份内容给i而已,i与age之间没有关系。

    function setAge(i)

    {
        alert(i);//24
        i = 18;
        alert(i);//18,i的改变不会影响外面的age
    };
     
    var age = 24;
    setAge(age);
    alert(age);//24

    当传入的参数为引用类型时:

    function setName(obj)

    {
        obj.name = 'haha';
    };
     
    var obj2 = new Object();
    setName(obj2);
    alert(obj2.name);    //  haha

    这看起来很像是传递的是引用,因为obj.name受到改变了,但其实不是,其实还是值,因为obj2本身的值就是新对象的地址,所以传进去的就是这个地址。

     

    这是阿里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仍然改变的)。

    var a = 30;var b = a;a = 20;console.log( b )
    var a = [1,2];var b = a;a[0] = 5;console.log( b )

  • 相关阅读:
    nova创建虚拟机源码分析系列之五 nova源码分发实现
    nova创建虚拟机源码分析系列之四 nova代码模拟
    nova创建虚拟机源码分析系列之三 PasteDeploy
    nova创建虚拟机源码系列分析之二 wsgi模型
    nova创建虚拟机源码分析系列之一 restful api
    devstack安装openstack newton版本
    openstack ocata版本简化安装
    openstack使用openvswitch实现vxlan组网
    OpenFlow协议1.0及1.3版本分析
    Python开发环境配置
  • 原文地址:https://www.cnblogs.com/cench/p/6019453.html
Copyright © 2011-2022 走看看