In fact, in the JS stack is more like a variant of the array, but there are no arrays so many methods, and no array so flexible. But both stacks and queues are more efficient and controllable than arrays. But in JS to want to simulate the stack, the main form of the basis is also an array.
Starting from this article, may be exposed to some prototype, prototype chains, classes, constructors and other related JS concepts, but there is not too much to introduce these concepts, when necessary to carry out some brief explanation, recommend you to see Uncle Tom's deep understanding of the JavaScript series, Wang Fu in-depth understanding of the great God JavaScript prototypes and Closures series. are very good depth of good text, recommended that you can learn in depth.
To implement a data structure, first you need to understand its rationale, then what is the stack? And how does it work?
A stack is an ordered collection that adheres to the principle of LIFO (last on first out ). both the newly added element and the element to be deleted are stored on the same side of the stack, called the top of the stack, and the other end is called the bottom of the stack. In the stack, the new elements are close to the top of the stack, and the old elements are near the bottom. In fact, you can simply understand the stack into a wooden bucket stacked into the items, and finally put in the top of the bucket, but also the first to take out, but the first put in the bottom of the bucket, only the top of all the items can be taken out after the bottom of the items.
For arrays, you can add elements, delete elements, get the length of an array, and return the corresponding subscript to get the value, so before we start constructing a stack, we need to understand what the stack has to do with the basics.
1, the pressure stack, also called into the stack, that is, the elements added to the stack. It's like a push in an array.
2, out of the stack, remove the elements of the top of the stack. It's like a pop in an array.
3. Get the element at the top of the stack without doing any other operations on the stack. It's like getting the corresponding value in the array by subscript.
4, judge whether the stack is empty. It's like judging whether the length of the array is 01.
5, empty the stack, that is, remove all the elements in the stack. It's like setting the length of the array to 01 samples.
6, get the number of elements in the stack. It is like the length property of an array.
So, I believe that I have a basic understanding of the stack, then we will look at how to implement a constructor function of a JS stack.
function Stack () { var items = []; // First, we implement a method of stacking, this method is responsible for adding elements to the stack, it is important to note that the method can only add elements to the top of the stack, that is, the tail of the stack. this function (ele) { Items.push (ele) }}varNew Stack ();
We declare a constructor, and life in the constructor is a private variable items, which serves as the basic support for our stack-class storage stack elements. Then, add a push method, which is used by this to point to the instance that called the method. We'll add other methods in this way, in turn.
functionStack () {varItems = []; //First, we implement a method of stacking, this method is responsible for adding elements to the stack, it is important to note that the method can only add elements to the top of the stack, that is, the tail of the stack. This. Push =function(ele) {Items.push (ele); } //then we add a method to the stack, and again, we can only remove the elements from the top of the stack. This. Pop =function(ele) {returnItems.pop (); } //look at the top of the stack, which is what the stack's tail element is This. Peek =function () { returnItems[items.length-1]; } //Check if the stack is empty This. IsEmpty =function () { returnItems.length = = 0; } //Check the length of the stack This. Size =function () { returnitems.length; } //Empty Stack This. Clear =function() {Items= []; } //printing elements inside a stack This. Print =function() {Console.log (Items.tostring ())}}
This allows us to create a stack completely through the constructor function. We can instantiate a stack object with the new command to test our stack.
var New Stack (); Console.log (Stack.isempty ()); // trueStack.push (1); Stack.print (); Stack.push (3); Stack.print (); Console.log (Stack.isempty ()) ; // falseConsole.log (Stack.size ()); // 2Stack.push (+); Stack.print (); Stack.pop (); Stack.print (); Stack.clear (); Console.log ( Stack.isempty ()); // true
We found out that our stack class was doing pretty well. So is there any other way to implement the Stack class? Before ES6 I may regret ignorant to you say No. But now we can take a look at some of the new stuff that ES6 brought us.
Before we begin to transform our stack class, we need to talk about several concepts of ES6. class syntax, symbol base type, and Weakmap. Simple explanation, to the back of the transformation will not be a face, and we want to know more in-depth ES6 new syntax, you can go to self-check.
The class syntax is simply a syntactic sugar, and its functional ES5 is completely achievable, just to read it more clearly and more like an object-oriented syntax.
Symbol is a new basic type of ES6, as mentioned in previous articles, ES5 has only 6 data types, but in ES6 there is a new data type symbol, which represents a unique value.
Weakmap, in simple terms, is the collection used to generate key-value pairs, just like an object ({}), and one of the important uses of Weakmap is to deploy private properties.
Of course, the simple introduction above is more than that, the real content is much more than this.
Then you know some of their basic meanings. Let's start rebuilding the Stack class.
class Stack {constructor () { This. Items = []; } push (Element) { This. Items.push (Element); } pop () {return This. Items.pop (); } peek () {return This. items[ This. items.length-1]; } isEmpty () {return This. Items.length = = 0; } size () {return This. Items.length; } clear () { This. Items = []; } toString () {return This. items.tostring (); } print () {Console.log ( This. items.tostring ())}}
This is a class to implement the stack classes, in fact, we can look at, in addition to using the constructor construction method, in fact, there is no fundamental difference.
Then we can also use the symbol data type to implement, simple transformation:
Const _ITEMS = Symbol (' Stackitems '); class Stack {constructor () { This[_items] = []; } push (Element) { This[_items].push (Element); } pop () {return This[_items].pop (); } peek () {return This[_items] [ This[_items].length-1]; } isEmpty () {return This[_items].length = = 0; } size () {return This[_items].length; } clear () { This[_items] = []; } print () {Console.log ( This. toString ()); } toString () {return This[_items].tostring (); }}
There is no big change in the use of symbol, just a unique _items is declared instead of the array in the construction method.
But there is a drawback to this approach, which is that ES6 's new Object.getownpropertysymbols method can read all the symbols properties declared within the class.
New= object.getownpropertysymbols (stack); Stack.push (1); Stack.push (3 // 1 // [Symbol ()] // Symbol ()stack[objectsymbols[0]].push (1// 1, 3, 1
I don't know, everyone. No, the symbol we define is outside the constructor, so anyone can change it. So the way is not perfect. Then we can also use ES6 's weakmap and then implement private properties with closures.
//turn declared variables into private properties by closuresLet Stack = (function () {//basic dependency of the declaration stackConst _ITEMS =NewWeakmap ();//declaring countersConst _COUNT =NewWeakmap (); class Stack {constructor () {//initializes the stack and counter values, where the set is the Weakmap's own method, set the values and values by set and get, where this is the key name of the setting value, what does this point? Self-console! _count.set ( This, 0); _items.set ( This, {}); } push (Element) {//get the length and the stack itself before going into the stackConst ITEMS = _items.get ( This); Const Count= _count.get ( This);//you have to pay attention here, _count, but starting from 0.Items[count] =element; _count.set ( This, Count + 1); } pop () {//if it is empty, then the stack cannot be if( This. IsEmpty ()) { returnundefined; }//get items and count to reduce the length by 1Const ITEMS = _items.get ( This); Let Count= _count.get ( This); Count--;//to re-assign a value to _count_count.set ( This, count);//removes the element from the stack and returns the elementConst RESULT =Items[count]; DeleteItems[count]; returnresult; } peek () {if( This. IsEmpty ()) { returnundefined; } Const Items= _items.get ( This); Const Count= _count.get ( This);//returns the top element of the stack returnItems[count-1]; } isEmpty () {return_count.get ( This) = = = 0; } size () {return_count.get ( This); } clear () {/*while (!this.isempty ()) {This.pop (); } */_count.set ( This, 0); _items.set ( This, {}); } toString () {if( This. IsEmpty ()) { return‘‘; } Const Items= _items.get ( This); Const Count= _count.get ( This); Let Objstring= ' ${items[0]}`; for(Let i = 1; i < count; i++) {objstring=' ${objstring},${items[i]} '; } returnobjstring; } print () {Console.log ( This. toString ()); }}returnStack;}) () const Stack=NewStack (); Stack.push (1); Stack.push (3); Stack.print (); //1, 3, 1
This is the final version of the more complete. So I don't know if you notice a small detail, before we just declare a variable, regardless of whether he is private, or array, the entire stack constructor is based on the items array to do various methods.
But here through Weakmap as the basic, we have used a _count, the front said _count is the counter, then why use counter? Because Weakmap is the "object type" of a key-value pair, it is not said to be as long as an array, so a counter is needed instead of the array's subscript to implement various stack-based methods.
Here we have basically finished our stack, and the next article will look at how we can do some interesting things with the stacks we've written.
Finally, because my level is limited, the ability and the great God is still very far apart, if there are errors or unclear, but also hope that everyone is not hesitate to correct. Thank you so much!
Using JS to implement those data structures (Stack 01)