摘要:中有三种数据结构栈堆队列。前端进击的巨人一执行上下文与执行栈,变量对象中解释执行栈时,举了一个乒乓球盒子的例子,来演示栈的存取方式,这里再举个栗子搭积木。对于基本类型,栈中存储的就是它自身的值,所以新内存空间存储的也是一个值。
面试经常遇到的深浅拷贝,事件轮询,函数调用栈,闭包等容易出错的题目,究其原因,都是跟JavaScript基础知识不牢固有关,下层地基没打好,上层就是豆腐渣工程,新人小白,踏实踩土才是关键。
打地基第二篇:本篇我们将对JavaScript数据结构的知识点详解一二。
JavaScript中有三种数据结构: 栈(stack) 、堆(heap)、 队列(queue)。
栈(stack)栈的特点是"LIFO,即后进先出(Last in, first out)"。数据存储时只能从顶部逐个存入,取出时也需从顶部逐个取出。《前端进击的巨人(一):执行上下文与执行栈,变量对象》中解释执行栈时,举了一个乒乓球盒子的例子,来演示栈的存取方式,这里再举个栗子搭积木。
举个栗子:乒乓球盒子/搭建积木
JavaScript中Array数组模拟栈:
var arr = [1, 2, 3, 4, 5]; arr.push(6); // 存入数据 arr -> [1, 2, 3, 4, 5, 6] arr.pop(); // 取出数据 arr -> [1, 2, 3, 4, 5]堆(heap)
堆的特点是"无序"的key-value"键值对"存储方式。
举个栗子:书架存书
我们想要在书架上找到想要的书,最直接的方式就是通过查找书名,书名就是我们的key。拿着这把key,就可以轻松检索到对应的书籍。
"堆的存取方式跟顺序没有关系,不局限出入口"。
队列 (queue)队列的特点是是"FIFO,即先进先出(First in, first out)" 。
数据存取时"从队尾插入,从队头取出"。
"与栈的区别:栈的存入取出都在顶部一个出入口,而队列分两个,一个出口,一个入口"。
举个栗子:排队取餐
JavaScript中Array数组模拟队列:
var arr = [1, 2, 3, 4, 5]; // 队尾in arr.push(6); // 存入 arr -> [1, 2, 3, 4, 5, 6] // 队头out arr.shift(); // 取出 arr -> [2, 3, 4, 5, 6]栈、堆、队列在JavaScript中的应用 1. 代码运行方式(栈应用/函数调用栈)
《前端进击的巨人(一):执行上下文与执行栈,变量对象》详解了JavaScript运行时的函数调用过程,而其中执行栈(函数调用栈)就是用到栈的数据结构。
JavaScript中函数的执行过程,其实就是一个入栈出栈的过程:
当脚本要调用一个函数时,JS解析器把该函数推入栈中(push)并执行
当函数运行结束后,JS解析器将它从堆栈中推出(pop)
具体执行过程可翻阅上篇文章《前端进击的巨人(一):执行上下文与执行栈,变量对象》,这里不再赘述。
2. 内存存储(栈、堆)JavaScript中变量类型有两种:
基础类型(Undefined, Null, Boolean, Number, String, Symbol)一共6种
引用类型(Object)
基础类型的值保存在栈中,这些类型的值有固定大小,"按值来访问";
引用类型的值保存在堆中,栈中存储的是引用类型的引用地址(地址指针),"按引用访问",引用类型的值没有固定大小,可扩展(一个对象我们可以添加多个属性)。
3. 事件轮询(队列)JavaScript中事件轮询(Event Loop)的执行机制,就是采用队列的存取方式,因事件轮询(Event Loop)也是JS基础中的一个比较难理解的知识点,后续另开一篇章再作详细探究。
深浅拷贝将一个变量的值赋值给另一个变量,相当于在栈内存中创建了一个新的内存空间,然后从栈中复制值,存储到这个新空间中。对于基本类型,栈中存储的就是它自身的值,所以新内存空间存储的也是一个值。直接改变新变量的值,不会影响到旧变量的值,因为他们值存储的内存空间不同。
// 基本类型复制变量 var a = 10; var b = a; b = 20; a // 10 b // 20
而对于引用类型来说,同样是复制栈中存储的值。但是栈存储的只是其引用地址,其具体的值存储在堆中。变量复制仅复制栈中存储的值,不会复制堆中存储的值,所以新变量在栈中的值是一个地址指针。
// 引用类型复制变量 var a = { age: 27 }; var b = a; b.age = 29; a.age == b.age; // 29
可见,变量复制赋值,都属于栈存储拷贝,因此深浅拷贝可以这样区分:
"浅拷贝:栈存储拷贝"
"深拷贝:栈堆存储拷贝"
深拷贝会同时开辟新的栈内存,堆内存空间。
// 利用JSON对象方法实现深拷贝 var a = { age: 27 }; var b = JSON.parse(JSON.stringify(a)); b.age = 29; a.age // 27 b.age // 29函数传参数是按值传递?按引用传递?
var person = { age: 27 }; function foo (person) { person.age = 29; } foo(person); person.age // 29;
函数调用时,会对参数赋值。而参数传递过程其实同样是变量复制的过程,所以它是按值传递。var person = person,因为传递参数是对象时,变量复制仅复制的栈存储(浅拷贝),所以修改对象属性会造成外部变量对象的修改。
至此,当我们理清栈、堆数据结构,以及JS中数据类型存取方式。深浅拷贝问题也就通顺了。
内存空间管理JavaScript执行过程中内存分配:
为变量对象分配需要的内存
在分配到的内存中进行读/写操作
不再使用时将其销毁,释放内存
内存管理不善,会出现内存泄露,造成浏览器内存占用过多,页面卡顿等问题。(后续性能优化篇章续讲)
垃圾回收机制JavaScript中有自动垃圾回收机制,会通过标记清除的算法识别哪些变量对象不再使用,对其进行销毁。开发者也可在代码中手动设置变量值为null(a = null)进行标记清除,让其失去引用,以便下一次垃圾回收时进行有效回收。
局部环境中,函数执行完成后,函数局部环境声明的变量不再需要时,就会被垃圾回收销毁(理想的情况下,闭包会阻止这一过程)。
全局环境只有页面退出时才会出栈,解除变量引用。所以开发者应尽量避免在全局环境中创建全局变量,如需使用,也要在不需要时手动标记清除,将其内存释放掉。
垃圾回收算法除了"标记清除",还有一种"引用计数",不常用,仅作了解。
参考文档:
stack的三种含义
内存空间详细图解
JavaScript变量——栈内存or堆内存
本文首发Github,期待Star!
https://github.com/ZengLingYong/blog
作者:以乐之名
本文原创,有不当的地方欢迎指出。转载请指明出处。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/101048.html
摘要:的垃圾回收器,进行回收。它们的数据就存放在堆内存中,大小不一定,动态分配内存,可随时修改。引用类型的变量存的是其在堆内存中的地址,值的读取,就是读取这个内存地址中储存的内容。 这东西还是很重要的,你要是搞懂了,就会去除很多困惑,比如不知道大家在学习js 的时候,有没有对 基础类型 和 引用类型 感到困惑过,两者之间 表现的不同之处。 js 不同其他编程语言,它是脚本语言。所以,它的数...
摘要:在中,通过栈的存取方式来管理执行上下文,我们可称其为执行栈,或函数调用栈。而处于栈顶的是当前正在执行函数的执行上下文,当函数调用完成后,它就会从栈顶被推出理想的情况下,闭包会阻止该操作,闭包后续文章深入详解。 写在开篇 已经不敢自称前端小白,曾经吹过的牛逼总要一点点去实现。 正如前领导说的,自己喝酒吹过的牛皮,跪着都得含着泪去实现。 那么没有年终完美总结,来个新年莽撞开始可好。 进击巨...
摘要:进击的巨人第三篇,本篇就作用域作用域链闭包等知识点,一一击破。在此我们遵照的方式,暂且称是闭包。所以,一名合格的前端,除了会用闭包,还要正确的解除闭包引用。 进击的巨人第三篇,本篇就作用域、作用域链、闭包等知识点,一一击破。 showImg(https://segmentfault.com/img/bVburWd?w=1280&h=854); 作用域 作用域:负责收集并维护由所有声明的...
摘要:有关函数柯里化的详解,请回阅前端进击的巨人五学会函数柯里化。构造函数中的通过操作符可以实现对函数的构造调用。在了解构造函数中的前,有必要先了解下实例化对象的过程。 showImg(https://segmentfault.com/img/bVburMp?w=800&h=600); 常见this的误解 指向函数自身(源于this英文意思的误解) 指向函数的词法作用域(部分情况) th...
摘要:隆重请出主角防抖与节流。防抖与节流的异同相同都是防止某一时间段内,函数被频繁调用执行,通过时间频率控制,减少回调函数执行次数,来实现相关性能优化。参考文章分钟理解的节流防抖及使用场景函数防抖和节流 showImg(https://segmentfault.com/img/bVburM8?w=800&h=600); 本篇课题,或许早已是烂大街的解读文章。不过春招系列面试下来,不少伙伴们还...
阅读 2306·2023-04-25 14:17
阅读 1514·2021-11-23 10:02
阅读 2169·2021-11-23 09:51
阅读 872·2021-10-14 09:49
阅读 3383·2021-10-11 10:57
阅读 2921·2021-09-24 09:47
阅读 3045·2021-08-24 10:00
阅读 2297·2019-08-29 18:46