值类型和引用类型

1.值类型(基本数据类型)

  • String
  • Number
  • Boolean
  • Undefined(变量申明未定义)
  • Null(空对象指针)
  • Symbol

值类型是存储在栈(stack)中的简单数据,也就是说,它们的值直接存储在变量访问的位置。

var num = 10;
var str = "hello JS";
var flag = true;
var un;
var nu = null;

typeof 类型: string,number,boolean,undefined,object,function

上面定义的这些值类型的数据在内存中的存储如下

2.引用类型(复合数据类型)

  • Object ( 数组/对象/函数)

存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存处。

var arr = [1, 2, 3];
var p1 = {name:"张三", age:18};
var p2 = {
    name:"李四",
    age:50,
    son:{
        name:"李小一",
        age:18
    }
};
var p3 = {
    name:"王五",
    age:50,
    children:[
        {
            name:"王小一",
            age:20
        },
        {
            name:"王小二",
            age:15
        },
        {
            name:"王小三",
            age:12
        }
    ]
}

上面定义的这些引用类型的数据在内存中的存储如下

值类型和引用类型的特征

1. 值类型和引用类型的赋值

1.1. 值类型赋值,直接将值复制一份

var num1 = 10;
var num2 = num1;

上面两句代码,在内存中的体现为:

  • var num1 = 10;表示变量num1存储的是数字10
  • 将数据拷贝一份,也就是将`10`拷贝一份,这个时候内存中有两个`10`
  • 将拷贝的10赋值给num2

1.2. 引用类型赋值,是将地址复制一份

var p = {name:"张三", age:19};
var p1 = p;

上面两句代码,在内存中的体现为:

  • var p = {name:"张三", age:19};p中存储的是对象的地址
  • 赋值就是将变量p中存储的数据,也就是地址拷贝一份, 然后将该数据赋值给p1
  • 此时内存中只有 1 个对象,变量pp1同时指向这个对象

问题: p1修改的name属性会影响到p中的name

2. 值类型和引用类型做参数

考虑如下情况:输出结果是多少?

function foo(num){
    num++;
}

var a = 1;
foo(a);
console.log(a);  // 1

继续考虑如下情况:输出结果是多少?

function foo(o){
    o.age++;
}
var p = {name:"张三", age:19};

foo(p);

console.log(p.age);  // 20

总结:

  • 在调用函数的时候,传参的过程其实就是用实参给形参赋值的过程
  • 参数为值类型的时候,函数内和函数外的两个变量完全不同,仅仅只是存的值一样而已,修改时互不影响
  • 参数为引用类型的时候,函数内和函数外的两个变量不同,但是共同指向同一个对象,在函数内修改对象数据时会影响外部

扩展:

考虑如下情况:输出结果是多少?

function foo(o){
    o = {name:"张三", age:18};
}

var p;
foo(p);

console.log(p.age);  
//VM856:10 Uncaught TypeError: Cannot read properties of undefined (reading 'age')

results matching ""

    No results matching ""