Blog icon indicating copy to clipboard operation
Blog copied to clipboard

变量和类型 - 变量在内存中的具体存储形式

Open logan70 opened this issue 5 years ago • 2 comments

变量在内存中的具体存储形式

基本类型变量的存储

  • 基本类型变量存储在栈内存中;
  • JS中基本类型值是不可变的,故基本类型变量改变时都会为变量重新分配内存并存储值。

下面例子说明了基本类型变量的声明、赋值及改变的过程。

// Step 1. `myNumber` -> Address: 0012CCGWH80 -> Value: 23
let myNumber = 23

// Step 2. `newVar` -> Address: 0012CCGWH80 -> Value: 23
let newVar = myNumber

// Step 3. `myNumber` -> Address: 0034AAAAH23 -> Value: 24
myNumber = myNumber + 1

基本类型变量的存储

基本类型变量的存储

基本类型变量的存储

栈内存 与 堆内存

JavaScript内存模型中,内存空间分为 栈内存(Stack)堆内存(Heap) 两种。

展开查看栈内存、堆内存的特点

栈内存特点

  • 存储的值大小固定
  • 空间较小
  • 可以直接操作其保存的变量,运行效率高
  • 由系统自动分配存储空间

堆内存特点

  • 存储的值大小不定,可动态调整
  • 空间较大,运行效率低
  • 无法直接操作其内部存储,使用引用地址读取
  • 通过代码进行分配空间

引用类型变量的存储

  • 引用类型变量(即Object类型)存储在堆内存中;
  • 堆内存中存储的引用类型变量值是可变的。

下面例子说明了引用类型变量的声明、赋值及改变的过程。

// Step 1. `myArray` -> HeapAddress: 22VVCX011 -> Value: []
let myArray = []

// Step 2. `myArray` -> HeapAddress: 22VVCX011 -> Value: ['first', 'second', 'third']
myArray.push('first')
myArray.push('second')
myArray.push('third')

引用类型变量的存储 引用类型变量的存储

变量的比较与传递

变量的比较,是按变量在栈内存中的值进行比较,

变量的拷贝与变量作为函数参数进行传递,也是按变量在栈内存中的值进行传递。

  • 对于基本类型变量来说,栈内存中的值即为其值本身;
  • 对于引用类型变量来说,栈内存中的值即为指向堆内存中引用类型值的地址。
// 变量比较
const num1 = 12
const num2 = 12

expect(num1 === num2).toBe(true)

const obj1 = { foo: 'foo' }
const obj2 = obj1
const obj3 = { foo: 'foo' }

expect(obj1 === obj2).toBe(true)
expect(obj1 === obj3).toBe(false)
// 变量传递
const changeNum = (num) => num++
const changeObj = (obj) => (obj = { foo: 'bar' })
const changeObjProp = (obj) => (obj.foo = 'bar')

const num = 1

changeNum(num)
expect(num).toBe(1)

const obj1 = { foo: 'foo' }
const obj2 = { foo: 'foo' }

changeObjProp(obj1)
expect(obj1).toEqual({ foo: 'bar' })

changeObj(obj2)
expect(obj2).toEqual({ foo: 'foo' })

logan70 avatar Nov 15 '19 01:11 logan70

const num = 1
changeNum(num)
expect(num).toBe(1)

请问为啥这里的changeNum(num)也是1呢?

lixialu avatar Sep 06 '20 09:09 lixialu

@lixialu 因为在changeNum(num)调用时,num只是作为一个值传入了changeNum,然后changeNum内部初始化了一个num变量,被复制1,自增到2,返回,但是调用的地方没有接函数返回值,这个2也就被垃圾回收了

logan70 avatar Sep 06 '20 13:09 logan70