首发地址:https://github.com/jeuino/Blo...
前言
在上一篇《JavaScript 之作用域与作用域链》中,介绍了什么是作用域,以及变量和函数在作用域中是如何查找的。原来本篇文章是想写执行上下文中的变量对象的,但是想在介绍变量和函数是如何引用的之前,先总结一下它们是如何存储的。所以调整了一下发文顺序。
在 JavaScript 中,我们经常会声明变量和函数,JavaScript 引擎在处理声明时,会在内存中开辟一块空间,用于存储变量或函数。那么变量和函数到底存储在哪里?我们一起来看下。
内存空间
首先我们需要了解几个概念:
- 栈内存(stack):栈内存中数据的存取方式为先进后出,后进先出。这个过程就像给枪上子弹,先上的子弹最后打出,后上的子弹先打出。
- 队列(queue):队列中的数据存取方式与栈正好相反,它是先进先出,后进后出。就像火车过山洞,火车头先进同时也是先出的,车尾后进后出。
- 堆内存(heap):堆内存中数据的存取是无序的,不需要像栈和队列一样,必须按照某种顺序进行。你只需要知道存储数据的地址,那么就可以根据地址随时将数据取出。就像书架一样,你只需要知道书名,就可以在书架上找到并取出。
那么 JavaScript 中声明的变量和函数是存储在哪里的呢?
- 基础数据类型(Undefined、Null、Boolean、String、Number):存储在栈中,按值访问。我们可以通过 JavaScript 直接操作保存在变量中的值。。
- 引用数据类型(Object):存储在堆中,按引用访问。堆中的数据是不允许通过 JavaScript 直接访问的,我们平时在操作对象时,实际上操作的都是对象的引用(地址指针)。对象的引用存储在栈中。
我们看下面的例子:
var a = 0;
var b = 'test';
var c = {a: 1};
var d = [1,2,3];
其中 a 和 b 两个基本数据类型数据存储在栈中;c 和 d 是引用类型,原始对象存储在堆中,并在栈中存储了引用地址。当我们访问 c 和 d 时,都需要先从栈中获取引用地址,然后根据引用地址到堆中找到相应的对象。
堆中原始的对象又是如何保存的呢?
堆中的原始的对象以字典结构保存,每一个属性名都对应一个属性描述对象。上面例子中变量c
的a
属性,实际上是以下面的形式保存的:
其中 [[value]]
属性保存的是该a
属性的值。(其他的属性,我们暂时不关注)
我们再来看一个例子:
function foo() {
}
var obj ={
foo: foo
}
这段代码中的 obj
对象是以下面的形式保存的:
其中,函数在堆中是单独存储的。
对象的属性值 foo,存储的其实是该函数的引用地址。即使 foo 函数是直接定义在 obj 中的也是一样。严格来说这个函数并不属于 obj 对象。
下一篇
下篇文章将接着上篇继续介绍执行上下文中的变量对象。
参考:
JavaScript 的 this 原理
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。