三者之间的关系
内存是一个容器,用来存储程序运行需要操作的数据(内存是用来存储数据的空间)。
变量是内存的标识,我们通过变量找到对应的内存,进而操作(读/写)内存中的数据。
情况讨论:var a = xxx(赋值操作),a内存中到底保存的是什么
首先将代码加载到内存中 然后编译 再然后解析执行
内存内容有两种数据 一种是基本数据 一种是地址值数据
var a = 3
var b = a
变量赋值是将a的值复制一份给b 对象是将地址给变量
什么是数据?
问题:var a = xxx(赋值操作),a内存中到底保存的是什么?
xxx是一个基本数据,保存的就是这个数据。
xxx是一个对象,保存的是对象的地址值。
xxx是一个变量![avatar](2.png),保存的xxx的内存内容(保存的可能是基本数据,也可能是地址值数据)
关于引用变量赋值问题
- 2个引用变量指向同一个对象(保存的内容是同一个对象的地址值),通过一个引用变量修改对象内部数据,另一个引用变量也看得见(看见的是修改之后的数据)。
- 2个引用变量指向同一个对象,让一个引用变量指向另一个对象,另一个引用变量还是指向原来的对象
此图,针对第1条解释
此图,针对第2条解释。
//1. 2个引用变量指向同一个对象, 通过一个引用变量修改对象内部数据, 另一个引用变量也看得见
var obj1 = {}
var obj2 = obj1
obj2.name = 'Tom'
console.log(obj1.name) // Tom
function f1(obj) {
obj.age = 12
}
f1(obj2)
console.log(obj1.age) // 12
//2. 2个引用变量指向同一个对象,让一个引用变量指向另一个对象, 另一个引用变量还是指向原来的对象
var obj3 = {
name: 'Tom'
}
var obj4 = obj3
obj3 = {
name: 'JACK'
}
console.log(obj4.name) // Tom
function f2(obj) {
obj = {
name: 'Bob'
}
}
f2(obj4)
console.log(obj4.name) // Tom
var a = {age: 12}; // 2个引用变量指向同一个对象
var b = a; // 2个引用变量指向同一个对象
a = {name: 'Bob', age: 13}; // 将新的对象赋值给a
b.age = 14; // 另一个引用变量还是指向原来的对象
console.log(b.age, a.name, a.age); // 14 "Bob" 13
function fn2 (obj) {
obj = {age: 15}; // 新的对象(垃圾对象)
}
fn2(a); // 函数执行完,函数内部的局部变量(obj)会自动释放
//总结:obj引用的地址值发生改变,不再引用传进来的形参地址,并且函数作用域的原因,这个对象只能在函数内使用。
console.log(a.age); // 13
</script>
obj和a存的堆地址相同,下一步赋值obj的堆地址改变了,但是他并没有改变之前a里存的堆地址的内容。
fn2(a)就是把a的内容(这里的内容是地址值)拷贝一份到函数参数obj上,但函数内部obj指向了新对象,但不影响a指向的对象。
函数形参传进去之后,复制a的值给obj,这两个栈内存指向一个堆内存的数据。之后obj={age:15},这时:obj指向另一个堆内存,这两个堆内存不一样了,再用obj修改age也不会影响到a指向的age
关于数据传递问题
问题:在js调用函数时传递变量参数时,是值传递还是引用传递?
理解1:都是值(基本/地址值)传递。
理解2:可能是值传递,也可能是引用传递(地址值)。
只有值传递,没有引用传递,传递的都是变量的值,只是这个值可能是基本数据,也可能是地址(引用)数据。
如果后一种看成是引用传递,那就值传递和引用传递都可以有。
函数也是在 堆空间 函数名在栈空间(本质上是一个变量名) 对象在堆空间是对象本身在堆空间
而标识这个对象的变量名在栈空间里
因为函数里的a是函数内的局部变量,换成this.a = a + 1,这时候this.a就是你最开始定义的a。
假设形参是x,调用函数传参时,发生了两件事:1、读取全局变量a的值;2、将值赋值给x ,然后执行函数内代码。
括号里的a是全局里的a的值copy给他的。
内存管理
问题:JS引擎如何管理内存?
1. 内存生命周期
1.分配小内存空间,得到它的使用权(分配需要的内存)。
2.存储数据,可以反复进行操作(使用分配到的内存)。
3.释放小内存空间(不需要时将其释放/归还)。
2. 释放内存
1.局部变量:函数执行完 自动释放(为执行函数分配的栈空间内存)。
2.对象:成为垃圾对象==>垃圾回收器回收(存储对象的堆空间内存:当内存没有引用指向时,对象成为垃圾对象,垃圾回收器后面就会回收释放此内存。)