day004 JavaScript知识合辑03——值类型与引用类型的区别
1.存储
值类型是存储在栈(stack)内存中的简单数据,它们的值直接存储在变量访问的位置。
var num = 10;
var str = "hello JS";
var flag = true;
var un = undefined;
var nu = null;
上面定义的这些值类型的数据在内存中的存储如下:
引用类型存储在堆(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
}
]
}
上面定义的这些引用类型的数据在内存中的存储如下:
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;
上面两句代码,在内存中的体现为:
引用类型赋值,是将地址复制一份。
var p = {name:"张三", age:19};
var p1 = p;
上面两句代码,在内存中的体现为:
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