javascript 内存模型实例详解

我对于 JavaScript 的内存模型一直都比较困惑,很想了解在操作变量的时候,JS 是如何工作的。如果你和我有同样的困惑,希望这篇文章能给你一些启发。

译文,喜欢原文的可以直接拉到底部

当我们声明变量、初始化变量、更改变量值的时候,到底会发生什么?JavaScript 是如何实现这些基本的功能?最重要的是,我们如何才能理解这些基础知识?

本文将覆盖以下 4 个方面:

JavaScript 原始数据类型的变量声明和赋值

JavaScript 内存模型:调用栈和堆

JavaScript 引用类型的变量声明和赋值

Let VS. const

JavaScript 原始数据类型的变量声明和赋值

从一个简单的栗子开始。首先我们声明一个叫myNumber的变量,赋值为 23。

let myNumber = 23

执行这段代码的时候,JavaScript 会...

为你的变量(myNumber)创建一个唯一标识符。

为变量分配一个内存地址(运行时)。

在分配的地址中存储一个值(23)。

javascript 内存模型实例详解

通常我们会说:“myNumber 等于 23”,但从技术上讲,myNumber 等于一个内存地址,那儿保存着一个大小为 23 的值。理解这段话十分关键。

如果我们创建一个 newVar 的新变量,然后把 myNumber 赋值给它:

let newVar = myNumber

因为 myNumber 实际上等于“0012CCGWH80”,那么newVar也等于“0012CCGWH80”,这个内存地址保存的值为 23。最终实现了“newVal 等于 23”的效果。

javascript 内存模型实例详解

如果我们这样做又会发生什么呢?

myNumber = myNumber + 1

显然,myNumber的值为 24,那么对于指向相同内存地址的newVar,它是否也等于 24?

答案当然是否定的!因为 JavaScript 的基本数据类型是不可变的,myNumber + 1的结果是 24,JavaScript 会分配一个新的内存地址来存储这个值,然后将myNumber指向这个新地址。

javascript 内存模型实例详解


图3

再举一个例子:

let myString = 'abc' myString = myString + 'd'

JS 新手可能认为,字符串abc已经存在于内存里,所以字母d只是追加到它的后面。从技术上讲,这是错误的。由于原始数据类型的不变性,当abc与d结合时,JS 会分配一个新的内存地址来保存这个值(abcd),接着myString指向新的地址。

javascript 内存模型实例详解


图4

JavaScript 的内存模型:调用栈和堆

JS 的内存模型可以简单的理解为两个不同的区域:调用栈和堆。

javascript 内存模型实例详解


图5

栈用来保存原始数据以及函数调用,可以粗略的用下图表示。

javascript 内存模型实例详解


图6

上图中,我抽象的在调用栈中显示每个变量的值。但请记住,变量实际指向的是内存地址,那里保存着对应的值。这是理解let vs. cont的关键。

关于堆内存。

堆保存着所有非原始类型的数据。它和栈最大的区别是,堆可以保存无序、能够动态增删的数据——对于对象和数组来说,这是完美的存储空间。

JavaScript 非原始数据类型的变量声明和赋值

还是从一个简单的栗子开始。下面,我们声明一个叫myArray的变量,并初始化一个空数组。

let myArray = []

当 JS 引擎执行上面的代码,内存会发生如下变化:

为变量(myArray)创建一个唯一标识符。

在栈中给变量分配一个地址a(运行时)。

在堆中分配一个地址b,用来存储值 [](运行时)。

地址a所存储的值为地址b

javascript 内存模型实例详解


图7

javascript 内存模型实例详解


图8

现在,我们可以对数组做任何操作了。

myArray.push('first') myArray.push('second') myArray.push('third') myArray.pop()

javascript 内存模型实例详解


图9

Let vs. const

我们应该优先使用const而不是let,除非变量会被改变。

我们必须清楚的知道——“改变”到底是什么意思。

值发生了变化,这是对“改变”的一种错误理解。一些 JS 程序员会写下这样的代码:

let sum = 0 sum = 1 + 2 let numbers = [] numbers.push(1) numbers.push(2)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/9f188d752f25179cb01d59f09b4bf089.html