引用类型和值类型
哪些是引用类型,哪些是值类型?
- undefined, number, string, boolean属于值类型,不是对象。
- 函数、数组、对象、null 都是对象。他们都是引用类型。
<script>
console.log(typeof(x)); // undefined 值类型
console.log(typeof(10)); // number 值类型
console.log(typeof(‘abc’)); // string 值类型
console.log(typeof(true)); // Boolean 值类型
console.log(typeof(function () { })); //函数 引用类型
console.log(typeof([1, ‘a’, true])); //数组 引用类型
console.log(typeof ({ a: 10, b: 20 })); //object 或json 引用类型
console.log(typeof (null)); //null 引用类型
console.log(typeof (new Number(10))); //内置对象 引用类型
内置对象目的将数值型转换成引用类型new Number(10)
</script>
值类型(基本类型)
<script>
var num1; /*这个时候不进行内存分配*/
var num3=9; /*分配内存*/
var num4=num3;/*分配内存 彼此拥有独立的内存空间,互不影响*/
console.log(num3) /*9*/
console.log(num4) /*9*/
num3=3333333;
num4=4444444;
console.log(num3) /*3333333*/
console.log(num4) /*4444444*/
</script>
- 把一个值类型(也可以叫基本类型)sum3传递给另一个变量sum4(赋值)时,其实是分配了一块新的内存空间,因此改变sum3的值对sum4没有任何影响。
引用类型
<script>
/*引用类型内存会产生两篇区域,一个存储变量,一个存储数组 变量中保存的只是数组所在的地址*/
var arr1=['苹果','橘子'];
var arr2=arr1;
console.log(arr1[0]); /*苹果*/
console.log(arr2[0]); /*苹果*/
//修改数组1
arr2[0]='香蕉';
console.log(arr1[0]); /*香蕉*/
console.log(arr2[0]); /*香蕉*/
</script>
引用类型的内存会开辟两个区域A和B,A区域用来存放变量名,存放的是一个地址或者说是一个指针,B区域存放的是实际内容。
把arr1赋值给arr2的过程,实际上只是在A区域保存了一个arr2的指针(地址),该指针指向的是B区域里面arr1的实际内容,所以改变arr1,arr2也会受影响。
引用类型的内存分配其实操纵的就是地址,arr1和arr2的地址指向同一片区域,所以修改arr1就是修改了arr2本身。
引用类型和值类型区别
- 内存分配机制不一样
- 值类型:每创建一个变量,内存都会创建一个新的区域来保存变量。当把一个变量A值赋给变量B时,实际上是为变量B创建一个新的区域。
- 引用类型:创建一个变量,引用类型会分配两个内存区域:一个保存地址,一个保存内容。当把一个变量A值赋给变量B时,只是创建一个区域来保存B的入口地址,A和B指向的内容都是一样的,即是A的内容。
<script>
function sum(num1,num2)
{
return num1 + num2;
}
console.log(sum(10,10)); /*20*/
var anotherSum = sum;
/*这里只是将内存中sum变量保存地址的区域赋值成了null,这样做并不会影响到sum函数保存实际内容的区域,所以anotherSum不受影响的*/
sum = null;
console.log(anotherSum(10,10)); /*20*/
console.log(sum(10,10)); /*sum is not a function*/
</script>
<script>
var a = {"x": 1};
var b = a;
a.x = 2;
console.log(b.x);
/*解析*/
/*将a赋值给b b中保存的只是地址,a变量,b变量指向同一个对象*/
/*修改a.x 同时也修改了b.x - 以为修改的都是同一块内存区域*/
/*2*/
var a = {"x": 1};
var b = a;
a.x = 2;
console.log(b.x);
a = {"x":3};
console.log(b.x);
/*解析*/
/*这里又定义了一个新的对象,重新分配内存空间,这个时候a变量中存储的是新地址,而b还是指向老对象*/
/*所以这里b.x还是2*/
/*2,2*/
var a = {"x": 1};
var b = a;
a.x = 2;
console.log(b.x);
a = {"x":3};
console.log(b.x);
a.x = 4;
console.log(b.x);
/*解析*/
/*a b这个时候分别指向不同的对象,所以修改a不会影响b*/
/*所以这里b.x还是2*/
/*2,2,2*/
</script>
<script>
var a = {n:1};
var b = a;
a.x = a = {n:2};
console.log(a.x); // undefined
console.log(b.x); // Object { n: 2 }
</script>
堆内存空间和栈内存空间
- 值类型:存放在栈内存空间。
- 堆类型:
- 栈:存放变量,变量中保存的只是对象所在的地址。
- 堆:保存对象真正的数据。