欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

day004 JavaScript知识合辑03——值类型与引用类型的区别

程序员文章站 2022-03-22 10:14:15
1.存储值类型是存储在栈(stack)内存中的简单数据,它们的值直接存储在变量访问的位置。var num = 10;var str = "hello JS";var flag = true;var un = undefined;var nu = null;上面定义的这些值类型的数据在内存中的存储如下:引用类型存储在堆(heap)内存中的对象,存储在栈内存的变量的值是一个指针(point),指向存储在堆内存的对象。准确地说,引用类型的存储需要内存的栈内存和堆内.....

1.存储

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

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

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

 

day004 JavaScript知识合辑03——值类型与引用类型的区别

引用类型存储在堆(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
        }
    ]
}

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

 

day004 JavaScript知识合辑03——值类型与引用类型的区别

2.访问

基本数据类型是按值访问的。基本类型的值是不可变的,基本类型的比较是它们的值的比较,数据类型不同也可以进行值的比较,这是因为在比较之前,自动进行了数据类型隐式转换。

var a,b;
a = "zyj";
b = a;
console.log(a);   // zyj
console.log(b);   // zyj
a = "呵呵";       // 改变 a 的值,并不影响 b 的值
console.log(a);   // 呵呵
console.log(b);   // zyj

js不同于其他语言,其不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间,实际上,是操作对象的引用,所以引用类型的值是按引用访问的

引用类型的值是可变的,引用类型的比较是引用的比较

var obj1 = {};    // 新建一个空对象 obj1
var obj2 = {};    // 新建一个空对象 obj2
console.log(obj1 == obj2);    // false
console.log(obj1 === obj2);   // false

//因为 obj1 和 obj2 分别引用的是存放在堆内存中的2个不同的对象,
//故变量 obj1 和 obj2 的值(引用地址)也是不一样的!

3.赋值(交换)

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

var num1 = 10;
var num2 = num1;

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

 

day004 JavaScript知识合辑03——值类型与引用类型的区别

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

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

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

day004 JavaScript知识合辑03——值类型与引用类型的区别

 

p中存储的是对象的地址,赋值就是将变量p中存储的数据,也就是地址拷贝一份, 然后将该数据赋值给p1,此时内存中只有 1 个对象,变量p和p1同时指向这个对象,利用p1修改的name属性会影响到p中的name。

 

4.做参数

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

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

总结:

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

5.通俗化理解

用“连锁店”和“连锁店钥匙”来理解。

(1)值类型:变量的交换等于在一个新的地方按照连锁店的规范标准(统一店面理解为相同的变量内容)新开一个分店,这样新开的店与其它旧店互不相关、各自运营。

把一个值类型(也叫基本类型)str2赋值给另一个变量时,其实是分配了一块新的内存空间,因此改变str1的值对str2没有任何影响,因为它不同于引用类型(变量的交换其实是交换了指像同一个内容的地址)。

在从一个变量向另一个变量赋值基本类型时,会在该变量上创建一个新值,然后再把该值复制到为新变量分配的位置上。

(2)引用类型:变量的交换等同于把现有一间店的钥匙(变量引用地址)复制一把给了另外一个老板,此时两个老板同时管理一间店,两个老板的行为都有可能对一间店的运营造成影响。

str2只进行了一次赋值,理论上它的值已定,但后面通过改写str1的值,发现str2的值也发生了改变,这正是引用类型的特点。引用类型的赋值其实是对象保存在栈区地址指针的赋值,因此两个变量指向同一个对象,任何的操作都会相互影响。

本文地址:https://blog.csdn.net/qq_45459315/article/details/109254081