js的内存机制(简单介绍)

js的内存机制

一、 介绍

简单的数据类型是放在栈中的,例如undefine,null,number,boolean,string,是直接引用的;

复杂的数据类型的放在堆中的,只是在栈中存放了一个地址,通过地址在堆中寻找数据,例如array,objec等。

注意点1:

let a = 10
let b = a 
b = 20

这个上面的a不会受到影响还是10,b变成了20

let objA = {a: 10, b: 20}
let objB = objA
objB.a = 30

这个时候,objA中的a变成了30

注意点2:

let str1 = new String('1')
let str2 = '2'

同样是string,str1使用new创建了一个新的对象,放在了堆中,而str2是之间存储在栈里面,str2的这种方式大大提高了程序运行速度

let str1 = 'abc'
let str2 = 'abc'

str1 == str2 //true
str1 === str2 //true

//这里str1和str2都只想栈里面的abc
//注:如果栈里面有当前数据,则引用直接只想栈里面已有的数据,不会创建新的,比如str2会先查看一下栈中是否有'abc',发现已经有了,直接指向了'abc'
let str1 = new String('abc')
let str2 = new String('abc')

str1 == str2 //false
str1 === str2 //false
//这里比较的是两个地址,指向的不是同一个对象
let str1 = new String('abc')
let str2 = 'abc'

str1 == str2 //true
str1 === str2 // flase

//逻辑等于,会将不同的类型转换为相同的类型,所以结果还是等于;逻辑全等,则先比较两者的数据类型,在看是否引用的同一份数据

还有一点,在string对象比较的时候,使用了+,要识别编译器最后能不能将两个string在编译阶段直降将两个相加的string合并为一个,如果能,则合并后的string是放在栈里面的,如果不能,则在运行时机合并,最后的string是放在堆里面的。

二、内存的释放

1. 堆内存的释放

对象数据或者函数类型在定义的时候,首先会开辟一个堆内存,堆内存有一个引用地址,如果外面有引用这个地址,则这个内存就被占用了,且不能销毁。

如果要将堆内存释放(销毁),只需要把引用它的变量赋值为空即可,当这个堆内存没有任何东西被占用,浏览器会在空闲的时候将它销毁。

2. 栈内存的释放

2.1 全局作用域

在全局作用域下,只有当页面关闭的时候,全局作用局才会被全销毁

2.2 私有作用域

一般情况下,函数执行会形成一个新的私有作用域,当私有作用域中的代码执行完成之后,当前作用域都会主动的进行释放和销毁

不过依然有特殊的情况存在:当前私有作用域中的部分内容被作用域以外的东西占用了,那么当前作用域就不能销毁了,

  • 函数返回了一个引用数据类型的值(数组,函数…),并且改引用类型的值在函数的外面被一个其他变量接收了,这种情况下形成的私有作用域都不会销毁。

注意两个条件:

1.函数返回运用数据类型的值,

2.改应用类型的值在函数外面被一个其他变量接受了

  • 在一个私有作用域中,给DOM元素绑定方法,私有作用域不能被销毁

  • “不立即销毁”

function fn() {
    var num = 100;
    return function () {
    }
}
fn()(); // 首先执行fn,返回一个小函数对应的内存地址,然后紧接着让返回的小函数再执行

这种情况不会立即销毁。

只要某作用域还有被引用,那么改作用域就不能被销毁,一单没有任何变量引用了,改私有作用域就会被销毁了

你可能感兴趣的:(JavaScript)