# 栈

栈和队列本质上也是数组，是较为特殊的两种。

栈是一种后入先出的有序集合，例如 js 的执行栈。

![](https://3490195898-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnQxDcxCKODvYvTUWe3%2F-Lxe-pKn0CXUlHLvS3Rq%2F-Lxe09_6i0eE-MWjj7j-%2Fimage.png?alt=media\&token=677c2f69-8a96-4f27-b536-6bd0e7d90ee4)

## 实现

```javascript
let Stack = (function(){
  let items = new WeakMap()
  class Stack {
    constructor () {
      items.set(this, [])
    }
    pop () { // 出栈
      return items.get(this).pop()
    }
    push (v) { // 入栈
      items.get(this).push(v)
    }
    peek () { // 获取当前栈顶
      return items.get(this)[items.get(this).length - 1]
    }
    size () { // 栈长度
      return items.get(this).length
    }
    isEmpty () { // 栈是否为空
      return items.get(this).length === 0
    }
    clear () { // 清空栈
      items.get(this).length = 0
    }
  }
  return Stack
})()

```

`WeakMap` 只接受对象类型作为键名，并且键名是弱引用类型的。弱引用是一种容易被垃圾回收机制回收的类型，只要垃圾回收机制发现一个对象**只被**弱引用类型所引用，那么这个对象就会被回收。上面代码中的 `this` 本身是一种强引用类型，但是 `this` 又被当作 `WeakMap` 的弱引用键名。因此当 `this` 实例被销毁的时候，`this` 原先所指向的对象的内存地址只存在 `WeakMap` 的弱引用了，所以，`WeakMap` 中对应的键值对都会在垃圾回收机制运行的时候被销毁。

## 测试

![](https://3490195898-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnQxDcxCKODvYvTUWe3%2F-Lxe-pKn0CXUlHLvS3Rq%2F-Lxe12x3HhRftaJVc-Zb%2Fimage.png?alt=media\&token=e49194f5-6f2f-443f-a1a1-fe2d5854045c)

如图所示，变量`a、b`创建了两个栈实例，并分别往各自栈里添加了一个数字元素。这时闭包`items`中是存在两个栈的。然后把变量 `b` 设为 `null` ，这时变量 `b` 所创建的栈实例对象失去了强引用，只剩下 `WeakMap` 键名的弱引用，但是打印出来的`items` 中仍然存在两个栈，因为此时垃圾回收机制没有运行。过了十秒之后，chrome 浏览器的垃圾回收机制触发，便把`items` 中的失效的栈清除了，此时打印出来 `itmes` 中只剩下一个栈了。（P.S. 经测试发现目前版本的V8引擎垃圾回收机制至多十秒就清一次啊）<br>
