什么是数据?
存储于内存中代表特定信息的一个内容。本质上是二进制。万物皆数据。函数也是数据。
什么是内存?
内存条通电后产生的临时存储空间。断电内存全部消失。
什么是变量?
值可以变化的量 , 由变量名和变量值组成。
内存是一个容器,用来存储数据,变量是内存的标识,通过变量名找到对应内存,进而可以读内存中的数据,通过变量值可以重新写内存中的数据。
关于赋值与内存的问题:
- 存储的值类型的判断
存储的值类型的判断:
var a = xxx;
//1,xxx表示基本数据: 比如var a = 3
//a内存中保存的就是数据xxx本身
//2,xxx表示对象/数组/函数:
//a内存中保存的就是指针地址
//3,xxx表示变量:
//比如: var b = 'www'; a = b; a内存中保存的是'www';
//再比如: var b = {}; a = b; a内存中保存的是指针地址;
//a内存中保存的都是xxx的内容
关于引用变量赋值问题:浅拷贝
引用变量存储的是地址值,地址值进行再次引用赋值,属于浅拷贝。可以使得多个引用变量指向同一个对象。即指向同一块内存空间。当通过一个变量改变了对象内部数据时,其他引用变量看到的也都是修改后的数据。
- 深拷贝浅拷贝理解:浅拷贝拷贝的是内存地址,当多个地址值相同时,指向同一个变量。任意一个地址值访问变量并修改,其他引用地址访问到的变量也是修改后的值。
由第3种情况,可推深拷贝浅拷贝情况:
以下是对浅拷贝的理解:
举例:
var a = {name:'tom'}; //a内存中保存的是地址
var b = a; //将a保存的内容赋值给b。所以b内存中保存的也是地址
a.name = 'jack'; //改变a地址指向的内存数据的属性值,
console.log(b.name);//由于b内存保存的也是同一个地址,指向同一块内存数据,所以结果也是'jack'
引用变量赋值问题理解的加深:
再举例:
let a = {name:'tom'};//a内存中保存的是地址
let b = a;//将a保存的内容赋值给b。所以b内存中保存的也是地址 所以a,b保存的是指向同一块内存空间的相同地址值。
b.age = 18;//给b指向的对象新增一个属性age,值18
console.log(a.age);//a指向的对象即b指向的对象,所以也存在age属性,值18
再举例:
let a = {age:7};//a内存中保存的地址
let b = a;//b内存中保存a的内容,即地址
a = {name:'77',age:9};//新的对象 {} 赋值给a,a内存中保存的是另一个地址 此时a,b指向的是两块不同的内存空间,互不影响。
console.log(b.age,b.name,a.age,a.name);// 7, undefined, 9, '77'
再举例:
let a = {age:7};//a内存中保存的地址
function fn(obj) {
obj = {age:0};
}
fn(a);
//a作为实参传入函数fn,赋值给形参,即obj = a。将a的内容赋值给obj,此时obj和a内存中保存的都是同一个地址值。
//函数内,将对象{}赋值给obj,此时obj保存的是另一个地址,即obj和a内存中分别保存的是两个不同的地址值,指向不同的内存空间,它们互不影响。
console.log(a.age);//所以输出 7
//而函数内的obj保存的地址值和指向的数据,属于局部变量,在函数被执行后,obj会被自动释放。后面的某个时刻会被垃圾回收机制处理。
关于数据传递的问题:
提问:在js调用函数传递变量参数时
,属于值传递还是引用传递?
答:属于值传递
。如上面的案例将a的值传递给obj。由于a保存的地址,所以obj也保存的是地址值。
举例:
let a = 1;
function fn(x) {
x = x+1;
}
fn(a);//将a的值传递给形参x,此时x的值为1,进行+1运算后,x的值为2。而a本身并没有被改变。所以a还是1
console.log(a);//1
理解:其实赋值都属于值传递。只不过值可能是基本类型,也可能是引用类型。可能是地址,可能是数据。
还有另外一种理解:认为传递的是指针时就是引用传递,传递的是数据时就是值传递。
我个人非常认同第一种理解。让人豁然开朗。
但不排除面试官会是第二种理解。假如面试被问到这个问题。要说清楚,不然面试官以为你不懂回答错了呢【视频学习时老师的建议:两种理解都说明。】
JS引擎如何管理内存:
内存生命周期:
- 分配小内存空间,得到使用权:
- 存储数据,可以反复进行操作:
- 释放小内存空间,将使用权交出去【否则,不释放会造成持续占用内存】
释放内存:
- 局部变量在函数执行完自动释放
- 对象:成为垃圾对象 => 后面的某个时刻被垃圾回收器回收
- 全局变量不会释放,除非关闭浏览器
函数作用域内变量【局部变量】在函数执行时产生,在函数执行结束后自动释放。后面的某个时刻会被垃圾回收机制处理。