JS知识点系列--基本类型与引用类型

变量的值类型

变量可能包含两种不同数据类型的值:基本类型值(简单的 数据段)和引用类型值(可能由多个值构成的对象)

变量的存储

  • 基本类型值在内存中占据固定大小空间,因此被保存在栈区;
  • 引用类型值是对象,引用类型的存储需要内存的栈区和堆区共同完成,栈区内存保存变量标识符和指向堆内存中该对象的指针,这个指针指向堆内存中的相应对象

栈:由操作系统自动分配释放
堆: 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收

变量的访问

五种基本数据类型是按值访问的,可以操作保存在变量中的实际的值 引用类型值 是保存在内存中 的对象,JS不允许直接访问内存中的位置,操作对象时实际上是在操作对象的引用而不是实际的对象,所以引用类型的值是按引用访问的(注意在为对象添加属性时操作的是实际的对象),当访问时,我们需要先从栈中读取内存地址,然后再顺藤摸瓜地找到保存在堆内存中的值

变量的复制

从一个变量num1向另一个变量num2复制 基本类型值;复制的是num1的值的一个副本,复制后这两个变量中的值是完全独立的 从一个变量向另一个变量复制引用类型的值

1
2
3
4
var obj1 = new Object();
var obj2 = obj1;
obj1.age = 18;
console.log(obj2.age); // 输出18

通过上面两个小节应该已经了解引用类型值是怎么存储的,现在用上面的代码简单解释下
对象Object是被保存在堆中,obj1被保存在栈中,obj1存储的内容是一个指针,指向堆中的实际对象Object,也就是说obj1存储的值是实际对象Object的地址,所以这样实现了按引用访问。
从变量obj1向另一个变量obj2复制 引用类型值时,复制的是obj1的值,由上所述可知是指向实际对象Object的指针,所以赋值后,obj2存储的值也就是指向实际对象Object的指针。而实际对象Object只有一个,所以obj1、obj2都指向它,也就是obj1、obj2引用同一个对象Object
所以会出现改变obj1会影响obj2的现象

传递参数
ECMAScript中所有的函数的参数 都是 按值传递,即使是引用类型值的传递也是按值传递

  • 传递基本类型值时,被传递的值会被复制给一个局部变量(即命名参数或者arguments中的一个元素)
  • 传递引用类型值时,由复变量的复制这一节已经知道,该值是一个指针,然后将其复制给一个局部变量(即命名参数或者arguments中的一个元素),这个局部变量再根据这个地址去按引用访问对象,因此这个局部变量的变化会反映在函数的外部。而不是因为它是按引用传递才导致局部变量的变化会反映在函数的外部。