栈内存和堆内存

我们知道程序是需要加载到内存中来执行的,我们可以将内存划分为两个区域:栈内存和堆内存

  • 原始类型占据的空间是在栈内存中分配的;
  • 对象类型占据的空间是在堆内存中分配的;

值类型和引用类型

  • 原始类型的保存方式:在变量中保存的是值本身;所有原始类型也被称之为值类型;
  • 对象类型的保存方式:在变量中保存的是对象的引用;所以对象类型也被称之为引用类型;
  1. JS代码是单线程的,代码从上到下执行,栈内存是先入后出的,所以上面的代码在栈的底部;

  2. 基本数据类型直接在栈内存中分配内存,变量保存的是值本身;

  3. 引用数据类型在堆内存中分配内存,并生成16进制地址,栈中的变量保存的是16进制地址,即对象的引用地址;

  4. 赋值操作是在栈中完成的:const nickName=name;将栈内存中name的值赋值给nickName,即nickName="fsllala";

    const info = obj;将栈内存中obj的内存地址赋值给info,即info=0x100;

1
2
3
4
5
6
7
8
9
10
const name = "fsllala";
const age = 18;
const obj = {
foo: "foo",
bar: 123
};
const nickName = name;
const info = obj;
info.foo = "hahaha";
console.log(obj.foo);

stack

变量的比较

基本数据类型比较的是值;引用数据类型比较的是地址;

1
2
3
4
5
6
7
const a = 123;
const b = 123;
console.log(a === b); //true

const m = {};
const n = {};
console.log(m === n); //false

heap

引用的赋值

info是个对象,在栈内存中保存的是一个指针,在堆内存中保存的是代码;info.friend又是一个对象,保存一个指针,在堆内存中开辟新的内存来保存info.friend中的代码;所以info.friend为一个指针,赋值给了friend;

1
2
3
4
5
6
7
8
9
const info = {
name: "why",
friend: {
name:"kobe"
}
};
const friend =info.friend;
friend.name="fsllala";
console.log(info.friend); //fsllala

fuzhi

值传递和引用传递的区别

值传递

在栈内存中进行赋值,const num = 100基本数据类型,直接赋值;foo(num)其实是foo(100);即a=100;然后又a=200

1
2
3
4
5
6
7
function foo(a) {
a = 200;
}

const num = 100;
foo(num);
console.log(num); //100

fuzhi

引用传递

在栈内存中进行赋值,引用数据类型赋值的是指针,在堆内存中保存代码;foo(obj)其实是foo(指针),即a=指针,紧接着,a={name:"why"},在堆内存中保存其代码,分配一个新的指针给a,即a=指针2

1
2
3
4
5
6
7
8
9
10
11
function foo(a) {
a = {
name: "why"
}
}

const obj = {
name: "obj"
}
foo(obj);
console.log(obj); //{name:"obj"}

obj

同上面相比,上面是新开辟了一个堆内存,这个是通过指针对堆地址的代码进行了修改;

1
2
3
4
5
6
7
8
9
function foo(a) {
a.name = "why";
}

const obj = {
name: "obj"
}
foo(obj);
console.log(obj.name); //why

obj