美文网首页菲麦前端
JS入门难点解析1-JS的数据类型和按值传参

JS入门难点解析1-JS的数据类型和按值传参

作者: love丁酥酥 | 来源:发表于2017-10-29 17:46 被阅读47次

    (注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!)
    (注2:更多内容请查看我的目录。)

    1. JS的数据类型

    JS变量的数据类型的值有两种:基本类型值和引用类型值。基本类型值指简单的数据段,而引用类型值指那些可能由多个值构成的对象。

    基本类型值有以下五种:Undefined、Null、Boolean、Number和String。引用类型值即保存在内存中的对象。

    var num1 = 1;
    var str1 = '1';
    
    1.1基本类型
    var obj1 = {a: 1};
    
    1.2引用类型

    2. JS的变量复制

    JS对基本类型的复制和引用类型的复制并不相同。基本类型值的复制实际上将变量和其存储的内容重新复制了一份,而引用类型的复制只是将其保存的指针复制了一份,实际存储对象的堆并没有复制。

    var num1 = 6;
    var num2 = num1;
    
    2.1基本类型复制
    var obj1 = {a: 1};
    var obj2 = obj1;
    
    2.2引用类型复制

    3. JS的参数传递是按值传参

    JS的参数是按值传递,即将函数外部的值复制给函数内部的参数,其复制过程如前所述。那么对内部变量值的改变是否会影响外部变量呢,这里我们用具体的例子来分析一下。

    function addTen(num) {
        num += 10;
        return num; 
    }
    var count = 20;
    var result = addTen(count); 
    alert(count); //20 没有改变   
    alert(result); //30
    

    我们可以看到,基本类型变量的传参对原变量并无影响,这一点大家也容易理解。可是对引用类型的传参呢?

    // eg3.1
    function setName(obj) {
        obj.name = "Nicholas";
    }
    var person = new Object();
    setName(person);
    alert(person.name);    //"Nicholas"
    

    我们发现原始变量person对象的name属性被改变了,这具有很强的迷惑性,会让人以为引用类型的传参是将整个引用对象存储的内容复制传递了。是否如此呢?我们看下面这个例子。

    // eg3.2
    function setName(obj) { 
        obj.name = "Nicholas";
        obj = new Object(); 
        obj.name = "Greg";
    }
    var person = new Object();
    setName(person);
    alert(person.name);    //"Nicholas"
    

    如果真的是按引用传递,那么最后person.name应该是'Greg'才对,但事实上却是'Nicholas',说明这里是并不是按引用传递。下面我们来一步步分析这两段代码的实际过程。

    对于eg3.1和eg3.2:

    step1: var person = new Object();执行完如下:


    step1

    step2: 进入setName(person);如下:


    step2

    step3: obj.name = "Nicholas";执行完如下:


    step3

    eg3.1的setName函数调用到此已结束,此时,person.name从图中可以看出是'Nicholas'。而对于eg3.2,其setName函数增加了两个步骤,如下:

    step4: obj = new Object();执行完如下:


    step4

    step5: obj.name = "Greg";执行完如下:


    step5

    可以看到,此时person.name仍然是'Nicholas'。

    现在,我们明白了,其实JS函数参数的传递始终是按值传递。但是在函数调用的过程中,我们到底是对该值指向的堆地址进行了操作,还是对该值进行了操作,决定了我们是否会对原变量产生影响。

    4. 测试一下

    看到这里,你应该已经掌握了JS的数据类型和按值传递。来做一个小测验,下面是两个对数组进行拼接并返回拼接后数组的函数,哪个函数在拼接的同时对传入的参数也产生了影响呢?(顺便学习一下es6的知识吧b( ̄▽ ̄)d)

    var fillArray = (arr, ...values) => {arr.push(...values);return arr;}
    
    var fillArray = (arr, ...values) => {arr = arr.concat(...values);return arr;}
    

    参考

    BOOK-《JavaScript高级程序设计(第3版)》 第3章

    相关文章

      网友评论

      • coffee_e50b:大佬,我的理解是实际上值是分两种的,一种是基本类型值复制传递,另一种是指向实参对象地址值复制传递,所以本质上都是值传递,而后一种被称为共享传递,call by share;而所谓的引用传递是将实参的引用真正的传递进入,而不是复制引用传递。所以感觉大佬其实不用解释那么复杂。
        coffee_e50b:@love丁酥酥 有道理,非英语母语,计算机最头疼的永远是概念。虽然我觉得看书其实是学习最好的方法,而不是视频,w3cscool等地方。就像大佬引用的js高级程序设计,其实很多知识点讲解很详细了。
        love丁酥酥:哈哈,不是大佬哈~~嗯,没听说过call by share这个词,特意查了下,其实对一个知识点来讲,懂的人可以精炼成自己的总结,可是不懂的人很难从纯概念的话来进行理解。如果懂的人可能不需要看这篇文章,但是不懂的人如果只看了这段概念他还是不懂。我的理解是,博客应该把自己懂的知识用浅显易懂的话告诉别人,让别人也理解~这篇文章除了传递一个概念,也是想传递一个概念理解的过程,另外也帮读者区分对于引用地址的操作和对实际引用操作的不同~~:smirk:
      • Love小六六:很棒,浅显易懂~✧*。٩(ˊᗜˋ*)و✧*。给男神点赞

      本文标题:JS入门难点解析1-JS的数据类型和按值传参

      本文链接:https://www.haomeiwen.com/subject/odyypxtx.html