栈是一个后进先出的数据结构 
JavaScript中没有栈,但可以用Array实现栈的所有功能 
栈常见操作:push、pop、stack[stack. length-1] 
1. 定义 后进先出,相当于往容器里放东西
用途:
编程语言的编译器和内存中保存变量、方法调用
浏览器历史记录(浏览器的返回按钮)
函数堆栈调用
……
 
2. 具体操作 创建 
1 2 3 4 5 class  Stack   {     constructor ( )  {         this .items = [];     } }
 
方法 :
push(element(s)):添加一个(或几个)新元素到栈顶
1 2 3 push (element )  {     this .items.push(element); }
 
 
pop():移除栈顶的元素,同时返回被移除的元素
1 2 3 pop ( )  { 	return  this .items.pop(); }
 
 
peek():返回栈顶的元素,不对栈做任何修改(该方法不会移除栈顶的元素,仅仅返回它)
1 2 3 peek ( )  {   	return  this .items[this .items.length - 1 ]; }
 
 
isEmpty():如果栈里没有任何元素就返回true,否则返回false
1 2 3 isEmpty ( )  {   	return  this .items.length === 0 ; }
 
 
clear():移除栈里的所有 元素
1 2 3 clear ( )  {   	this .items = []; }
 
 
size():返回栈里的元素个数(和length 属性类似)
1 2 3 size ( )  {   	return  this .items.length; }
 
 
 
3. 使用 1 2 3 4 5 6 7 8 9 10 11 const  stack = new  Stack();  console .log(stack.isEmpty());   stack.push(5 );  console .log(stack.peek());  console .log(stack.size());    console .log(stack.isEmpty());   stack.push(8 ); stack.push(11 ); stack.pop();  stack.pop();  console .log(stack.size());  
 
4. 基于JavaScript对象的Stack类 
最简单的方式:使用数组来存储其元素
 
基本结构:
1 2 3 4 5 6 7 class  xxx   {  constructor ( )  {       	}   }
 
5. 保护数据结构内部元素 使用 “_”  “#” 前缀来声明私有属性,需要编写相应的代码逻辑
使用es6中的Symbol
使用es6中的WeakMap
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 const  items = new  WeakMap ();class  Stack   {     construtor ( )  {         items.set(this , []);     }     push (element )  {         const  s = items.get(this );         s.push(element);     }     pop ( )  {         const  s = items.get(this );         const  r = s.pop();         return  r;     } }
 
6. 应用 十进制 —> 二进制 通过二进制的计算方法,可以知道二进制的结果是余数从高位到低位排列的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 decimalToBinary = (decNumber ) =>  {     const  remStack = new  Stack();     let  number = decNumber;     let  rem;     let  binaryString = '' ;     while  (number > 0 ) {         rem = Math .floor(number % 2 );         remStack.push(rem);         number = Math .floor(number / 2 );     }     while  (!remStack.isEmpty()) {         binaryString += remStack.pop().toString();     }     return  binaryString; }
 
其他进制转换 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 function  baseConverter (decNumber, base )  {       const  remStack = new  Stack();     const  digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' ;     let  number = decNumber;     let  rem;     let  baseString = '' ;     if  (!(base >= 2  && base <= 36 )) {         return  '' ;     }     while  (number > 0 ) {     rem = Math .floor(number % base);     remStack.push(rem);        number = Math .floor(number / base);     }     while  (!remStack.isEmpty()) {         baseString += digits[remStack.pop()];      }     return  baseString; }console .log(baseConverter(1111111 , 3 ));
 
函数的堆栈调用 1 2 3 4 5 6 7 const  func1 = () =>  {     func2(); }const  func2 = () =>  {     func3(); }const  func3 = () =>  {}
 
我们使用node进行debug:
可以看到,实际上,函数的调用也是满足后进先出的顺序
即,func3()最后进去,最先执行完的是func3()
一道LeetCode题 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 var  isValid = function (s )  {     const  stack = [];     for (let  i = 0 ; i < s.length; i++) {         const  c = s[i];         if (c === '('  || c=== '{'  || c === '[' ) {             stack.push(c);         } else  {             const  t = stack[stack.length - 1 ];              if (                 (t === '('  && c ===  ')' ) ||                 (t === '{'  && c ===  '}' ) ||                 (t === '['  && c ===  ']' )              ) {                 stack.pop();             } else  {                 return  false ;             }         }     }     return  stack.length === 0 ; };