美文网首页
JavaScript基本类型和引用类型的值

JavaScript基本类型和引用类型的值

作者: Julian1009 | 来源:发表于2017-11-28 01:01 被阅读0次

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

    在将一个值赋给变量时,解析器必须确定这个值是基本类型值还是引用类型值。第3章讨论了5种基本数据类型:UndefinedNullBooleanNumberString。这5种基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。

    引用类型的值是保存在内存中的对象。与其他语言不同,JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。为此,引用类型的值是按引用访问的1。

    动态的属性

    定义基本类型值和引用类型值的方式是类似的:创建一个变量并为该变量赋值。
    但是当这个值保存到变量中以后,对不同类型值可以执行的操作是不同的。
    我们可以为引用类型值添加属性和方法,也可以改变和删除。

    var person = new Object();
    person.name = 'John';
    console.log(person.name) // 'John'
    

    如果对象不被销毁或者这个属性不被删除,则这个属性将一直存在。
    但是,不能为基本类型值添加属性

    var name="John";
    name.age = 18;
    console.log(name.age) // undefined
    

    为字符串·name定义了一个名为age的属性,并为该属性赋值27。但在下一行访问这个属性时,发现该属性不见了。这说明只能给引用类型值动态地添加属性,以便将来使用。

    复制变量值

    从一个变量向另一个变量复制基本类型值和引用类型值时,也存在不同。
    基本类型值:

    var num1 = 5;
    var num2 = num1;
    
    image.png
    引用类型值:
    var obj1 = new Object();
    var obj2 = obj1;
    obj1.name = "Nicholas";
    alert(obj2.name);  //"Nicholas"
    

    首先,变量obj1保存了一个对象的新实例。然后,这个值被复制到了obj2中;换句话说,obj1obj2都指向同一个对象。这样,当为obj1添加name属性后,可以通过obj2来访问这个属性,因为这两个变量引用的都是同一个对象。

    image

    传递参数

    基本类型值:

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

    引用类型值:

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

    以上代码中创建一个对象,并将其保存在了变量person中。然后,这个变量被传递到setName()函数中之后就被复制给了obj。在这个函数内部,objperson引用的是同一个对象。换句话说,即使这个变量是按值传递的,obj也会按引用来访问同一个对象。于是,当在函数内部为obj添加name属性后,函数外部的person也将有所反映;因为person指向的对象在堆内存中只有一个,而且是全局对象。

    注:有很多开发人员错误地认为:在局部作用域中修改的对象会在全局作用域中反映出来,就说明参数是按引用传递的。为了证明对象是按值传递的,我们再看一看下面这个经过修改的例子:

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

    这个例子与前一个例子的唯一区别,就是在setName()函数中添加了两行代码:一行代码为obj重新定义了一个对象,另一行代码为该对象定义了一个带有不同值的name属性。在把person传递给setName()后,其name属性被设置为"John"。然后,又将一个新对象赋给变量obj,同时将其name属性设置为"Greg"。如果person是按引用传递的,那么person就会自动被修改为指向其name属性值为"Greg"的新对象。但是,当接下来再访问person.name时,显示的值仍然是"John"。这说明即使在函数内部修改了参数的值,但原始的引用仍然保持未变。实际上,当在函数内部重写obj时,这个变量引用的就是一个局部对象了。而这个局部对象会在函数执行完毕后立即被销毁。

    检测类型

    typeof操作符:

    var s = "Nicholas";
    var b = true;
    var i = 22;
    var u;
    var n = null;
    var o = new Object();
    
    alert(typeof s);   //string
    alert(typeof i);   //number
    alert(typeof b);   //boolean
    alert(typeof u);   //undefined
    alert(typeof n);   //object
    alert(typeof o);   //object
    

    instanceof操作符:

    alert(person instanceof Object);     // 变量person是Object吗?
    alert(colors instanceof Array);      // 变量colors是Array吗?
    alert(pattern instanceof RegExp);    // 变量pattern是RegExp吗?
    

    根据规定,所有引用类型的值都是Object的实例。因此,在检测一个引用类型值和Object构造函数时,instanceof操作符始终会返回true。当然,如果使用instanceof操作符检测基本类型的值,则该操作符始终会返回false,因为基本类型不是对象。

    相关文章

      网友评论

          本文标题:JavaScript基本类型和引用类型的值

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