怎样理解基本类型(原始类型)的数据和引用类型的数据

前言: 数值 / 字符串 / 布尔值 是基本类型, 对象 / 数组 / 函数是引用类型

ES5中有6种数据类型, 分别为: number / string / boolean / null / undefined / object. 这里的对象是广义的对象, 还可以细分为: array / function / object等. 

typeof(1); // "number"
typeof("1"); // "string"
typeof(true); // "boolean"
typeof({}); // "object"
typeof(null); // "object"
typeof(undefined); // "undefined"

// 数组也是对象
typeof([1,2,3]); // "object"

// 函数也是对象
var aFunc = function() {};
typeof(aFunc); // "function";
aFunc instanceOf Object; // true

其中, number / string / boolean 为基本类型, 也叫作: 原始类型; 而 object 则是引用类型, 这里的null 和 undefined有点特殊, 暂时不管它;

注意: 

1. 尽管typeof(null)为"object", 但: null instanceOf Object 为 false.

2. typoof(undefined) 为 "undefined";

第一步: 基本类型的数据存储在栈内存中

什么是栈内存呢? 我们目前可以简单理解为是下面这样, 在取得栈内存中的数据时的过程是根据变量名, 找到对应的内存地址, 再把内存地址中的数据取出来.

也就是说,  栈内存中的数据不能还是内存地址, 只能是特定的值, 这个值其实就是我们说的基本类型. 比如下面这段代码, 我们声明一个叫做: name的变量, 此时内存中就将一个内存地址同这个name作绑定, 然后我们给它赋值一个字符串: "hanmeimei", 这时内存中就会创建一个字符串数据: "hanmeimei", 并且将这个数据所在的内存地址"绑定"到变量名name上. 这样就实现了赋值.

当我们修改这个这个值为 "lilei"时, 实际上是修改了name指向的内存地址, 此时name将不再指向"hanmeimei"所在的内存地址.

// 声明一个变量, 因为变量没有赋值, 因此指向 undefined;
var name; 

// 赋值, 内存中新创建的 "hanmeimei" 数据的地址绑定到了 name上, name不再指向 undefined;
name = "hanmeimei";

// name 指向内存中新创建的 "lilei" 数据所在的内存地址, 不再指向 "hanmeimei"所在的内存地址
name = "lilei";

上面这一过程经历了下面的过程:  

 

注意: 

1. JavaScript中一切皆对象, 基本类型也是如此, 只是他们的对象特征体现在他们各自的包装对象上.

2. 真实的作用过程远比上图描述的复杂, 这里仅作演示;

3. 如果一个数据没有被任何变量所指向, 那这个数据将会被垃圾回收机制所销毁, 内存将会释放;

第二步: 引用类型的数据存储在堆内存中

堆内存是内存中另一种数据组织方式, 不同于栈内存中的 变量 => 内存地址  => 数据这种引用方式, 堆内存中的存储的数据还是内存地址, 也就是说: 从堆内存中取数据要不断地去找数据中内存地址指向的数据, 如果仍旧是内存地址, 则继续往下找. 比如下面这个数组中的数据就是最简单的堆内存: 

var family, son;

son = "liqiang";

family = ["lilei", "hanmeimei", son];

对应的演示图如下: 

 

注意: 

1. 基本类型无法被修改, 只能被覆盖, 原因是基本类型指向的内存地址里面的数据无法被修改, 只能新建一个数据, 把变量名指向这个内存地址;

2. 原始类型可以被修改, 指的是它指向的内存地址里面的内存地址可以被修改, 比如上面的000009地址里面的数据, 完全可以再加其他的. 不过加的也只能是内存地址;

3. 类似String.prototype.replce()一类的类型原始的方法, 产生的数据都是在一个新的内存地址上, 因为它无法做到改变自身.

猜你喜欢

转载自www.cnblogs.com/aisowe/p/11586433.html
今日推荐