栈(stack) 栈stack为自动分配的内存空间,它由系统自动释放
堆(heap) 堆heap是动态分配的内存,大小不定也不会自动释放
动态演示地址
var obj = {'name': 'along'}
堆内存 |
|
{'name': 'along'} |
指针 |
obj2 = obj
堆内存 |
|
{'name': 'along'} |
指针 |
{'name': 'along'} |
指针 |
结论:你会发现,如果是引用类型复制的话,虽然会有两个指针,但是指向都是同一个对象,这就会造成如果改变obj2值,也会造成obj值的改变。
如下图所示:栈内存中存放的只是该对象的访问地址, 在堆内存中为这个值分配空间 。 由于这种值的大小不固定,因此不能把它们保存到栈内存中。但内存地址大小的固定的,因此可以将内存地址保存在栈内存中。 这样,当查询引用类型的变量时, 先从栈中读取内存地址, 然后再通过地址找到堆中的值。
var a = 2;
栈内存 |
|
a |
2 |
b = a
栈内存 |
|
a |
2 |
b |
2 |
结论:栈内存虽然复制了a,但是创建了新的队列。修改b的值的同时也不会改变a的值。
使用数组实现栈的结构
function stack(){ let items = []; this.size = function(){ return items.length } this.push = function(item){ items.push(item) } this.pop = function(){ let item = items.pop() console.log('pop',item) return item } this.top = function(){ let length = items.length; console.log('top',items[length-1]) } this.show = function(){ console.log(items) } this.clear = function(){ items.length = 0 } this.isempty = function(){ console.log(items.length === 0) return items.length === 0 } } let newstack = new stack(); newstack.push(12); newstack.show() newstack.top() newstack.pop(); newstack.isempty(); newstack.show() newstack.push(1); newstack.push(5); newstack.isempty(); newstack.top() newstack.show() newstack.clear(); newstack.show()
调用堆栈会一直增长,直到达到限制,浏览器硬编码堆栈大小或内存耗尽。所以在用递归函数时要给一个终止条件。
var count = 1; function fn() { count++; fn() } fn() //maximum call stack size exceeded
pushstate,它会向浏览器的历史堆栈压入一个url为设定值的记录,并改变历史堆栈的当前指针至栈顶。
history.pushstate(stateobject, title, url) stateobject:state是一个由 pushstate()方法创建的、与历史纪录相关的js对象。当用户定向到一个新的状态时,会触发popstate事件。事件的state属性包含了历史纪录的state对象。 title:目前大多浏览器都忽视,传递空即可 url:新历史记录的url地址
replacestate:与pushstate参数相同,含义也相同。唯一的区别在于replacestate是替换浏览器历史堆栈的当前历史记录为设定的url。需要注意的是,replacestate不会改动浏览器历史堆栈的当前指针。
onpopstate:该事件是window的属性。该事件会在调用浏览器的前进、后退以及执行history.forward、history.back、和history.go触发,因为这些操作有一个共性,即修改了历史堆栈的当前指针。在不改变document的前提下,一旦当前指针改变则会触发onpopstate事件。
创建一个新的浏览器记录状态
const state = { 'page_id': 1, 'user_id': 5 } const title = '' const url = 'hello-world.html' history.pushstate(state, title, url)
总结:
浏览器针对每个页面维护一个history栈。执行pushstate函数可压入设定的url至栈顶,同时修改当前指针
当执行back操作时,history栈大小并不会改变(history.length不变),仅仅移动当前指针的位置
详细查看:
如对本文有疑问, 点击进行留言回复!!
荐 超强的入门文章 !!! JavaScript 速成计划第二篇(杂项详解:JS操作HTML 与 CSS、异常、事件)!
教你搭建 nodejs+mongoose+Graphql+Vue+Typescript 框架(上)
【Nginx】如何为已安装的Nginx动态添加模块?看完我懂了!!
网友评论